summaryrefslogtreecommitdiffstats
path: root/cfe
diff options
context:
space:
mode:
authorroot <root@lamia.panaceas.james.local>2015-12-19 13:13:57 +0000
committerroot <root@lamia.panaceas.james.local>2015-12-19 14:18:03 +0000
commit1a2238d1bddc823df06f67312d96ccf9de2893cc (patch)
treec58a3944d674a667f133ea5a730f5037e57d3d2e /cfe
downloadbootloader-1a2238d1bddc823df06f67312d96ccf9de2893cc.tar.gz
bootloader-1a2238d1bddc823df06f67312d96ccf9de2893cc.tar.bz2
bootloader-1a2238d1bddc823df06f67312d96ccf9de2893cc.zip
CFE from danitool [without hostTools dir]: https://mega.nz/#!mwZyFK7a!CPT3BKC8dEw29kubtdYxhB91G9vIIismTkgzQ3iUy3k
Diffstat (limited to 'cfe')
-rwxr-xr-xcfe/build/broadcom/bcm63xx_ram/Makefile76
-rwxr-xr-xcfe/build/broadcom/bcm63xx_rom/Makefile160
-rw-r--r--cfe/cfe/api/Makefile47
-rw-r--r--cfe/cfe/api/cfe_api.c534
-rw-r--r--cfe/cfe/api/cfe_api.h192
-rw-r--r--cfe/cfe/api/cfe_api_int.h168
-rw-r--r--cfe/cfe/api/cfe_error.h101
-rw-r--r--cfe/cfe/applets/Makefile64
-rw-r--r--cfe/cfe/applets/README21
-rw-r--r--cfe/cfe/applets/cfe_applet.lds37
-rw-r--r--cfe/cfe/applets/download.c163
-rw-r--r--cfe/cfe/applets/download.lds12
-rw-r--r--cfe/cfe/applets/minicrt0.S95
-rw-r--r--cfe/cfe/applets/test.c211
-rw-r--r--cfe/cfe/applets/vapitest.S96
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm63xx_util.h167
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_common.h32
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_cpu.h32
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_map.h32
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/include/bcmmii.h164
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/include/bcmtypes.h144
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/include/bsp_config.h94
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/include/dev_bcm63xx_eth.h127
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/include/dev_bcm63xx_flash.h38
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/include/jffs2.h251
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/Makefile55
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_board.c830
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_cmd.c1878
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_devs.c734
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_env_subr.c277
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_httpd.c1031
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_elf.c388
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_raw.c368
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_main.c611
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_net_icmp.c199
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ram_boot.S88
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_util.c1375
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_eth.c547
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_flash.c629
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_uart.c211
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/html/ul.html48
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/html/ulinfo.html60
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/ram_cfe.mk378
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/robosw_reg.c615
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_rom/src/Makefile23
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_rom_boot.S548
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_sdramDqs.c439
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_impl1_rom_boot.S1818
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_main.c649
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_rom/src/memtest.c1031
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_rom/src/rom_cfe.mk370
-rw-r--r--cfe/cfe/arch/mips/common/include/addrspace.h63
-rw-r--r--cfe/cfe/arch/mips/common/include/disasm.h61
-rw-r--r--cfe/cfe/arch/mips/common/include/exception.h223
-rw-r--r--cfe/cfe/arch/mips/common/include/exchandler.h85
-rw-r--r--cfe/cfe/arch/mips/common/include/initdata.h68
-rw-r--r--cfe/cfe/arch/mips/common/include/lib_hssubr.h84
-rw-r--r--cfe/cfe/arch/mips/common/include/lib_physio.h100
-rw-r--r--cfe/cfe/arch/mips/common/include/lib_setjmp.h81
-rwxr-xr-xcfe/cfe/arch/mips/common/include/mipsmacros.h376
-rwxr-xr-xcfe/cfe/arch/mips/common/include/segtable.h97
-rwxr-xr-xcfe/cfe/arch/mips/common/src/Makefile38
-rw-r--r--cfe/cfe/arch/mips/common/src/cfe_ram_cached.lds40
-rw-r--r--cfe/cfe/arch/mips/common/src/cfe_ram_uncached.lds40
-rwxr-xr-xcfe/cfe/arch/mips/common/src/cfe_ramapp.lds41
-rwxr-xr-xcfe/cfe/arch/mips/common/src/cfe_rom_cached.lds40
-rw-r--r--cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached.lds43
-rw-r--r--cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached_biendian.lds49
-rw-r--r--cfe/cfe/arch/mips/common/src/cfe_rom_reloc_uncached.lds41
-rw-r--r--cfe/cfe/arch/mips/common/src/cfe_rom_uncached.lds39
-rw-r--r--cfe/cfe/arch/mips/common/src/dev_flash_all.S220
-rw-r--r--cfe/cfe/arch/mips/common/src/dev_flashop_engine.S695
-rw-r--r--cfe/cfe/arch/mips/common/src/disasm.c2111
-rw-r--r--cfe/cfe/arch/mips/common/src/exception.S546
-rw-r--r--cfe/cfe/arch/mips/common/src/exchandler.c580
-rwxr-xr-xcfe/cfe/arch/mips/common/src/init_mips.S683
-rwxr-xr-xcfe/cfe/arch/mips/common/src/init_ram.S889
-rw-r--r--cfe/cfe/arch/mips/common/src/lib_hssubr.S194
-rw-r--r--cfe/cfe/arch/mips/common/src/lib_physio.S173
-rw-r--r--cfe/cfe/arch/mips/common/src/lib_setjmp.S94
-rw-r--r--cfe/cfe/arch/mips/common/src/mips_arena.c186
-rwxr-xr-xcfe/cfe/arch/mips/common/src/tools.mk83
-rw-r--r--cfe/cfe/arch/mips/common/src/ui_memtest.c282
-rw-r--r--cfe/cfe/arch/mips/cpu/SIBYTE_PRIVATE_FILES2
-rw-r--r--cfe/cfe/arch/mips/cpu/bcmcore/include/bcm4710.h58
-rw-r--r--cfe/cfe/arch/mips/cpu/bcmcore/include/bcm47xx.h8
-rw-r--r--cfe/cfe/arch/mips/cpu/bcmcore/include/bcmnvram.h123
-rwxr-xr-xcfe/cfe/arch/mips/cpu/bcmcore/include/cpu_config.h62
-rw-r--r--cfe/cfe/arch/mips/cpu/bcmcore/include/sbmips.h670
-rw-r--r--cfe/cfe/arch/mips/cpu/bcmcore/include/sbsdram.h92
-rwxr-xr-xcfe/cfe/arch/mips/cpu/bcmcore/src/Makefile8
-rwxr-xr-xcfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_arena.c170
-rwxr-xr-xcfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_cpuinit.S490
-rwxr-xr-xcfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_l1cache.S219
-rw-r--r--cfe/cfe/dev/SIBYTE_PRIVATE_FILES6
-rw-r--r--cfe/cfe/dev/bcm5700.h1007
-rw-r--r--cfe/cfe/dev/bcm5821.h278
-rw-r--r--cfe/cfe/dev/dc21143.h588
-rw-r--r--cfe/cfe/dev/dev_atapi.c222
-rw-r--r--cfe/cfe/dev/dev_bcm1250.c275
-rw-r--r--cfe/cfe/dev/dev_bcm5700.c2557
-rw-r--r--cfe/cfe/dev/dev_bcm5821.c1592
-rw-r--r--cfe/cfe/dev/dev_dc21143.c2388
-rw-r--r--cfe/cfe/dev/dev_dp83815.c2290
-rw-r--r--cfe/cfe/dev/dev_ds17887clock.c422
-rw-r--r--cfe/cfe/dev/dev_flash.c1367
-rw-r--r--cfe/cfe/dev/dev_ht7520.c167
-rw-r--r--cfe/cfe/dev/dev_ide_common.c1249
-rw-r--r--cfe/cfe/dev/dev_ide_pci.c358
-rw-r--r--cfe/cfe/dev/dev_newflash.c1428
-rw-r--r--cfe/cfe/dev/dev_ns16550.c255
-rw-r--r--cfe/cfe/dev/dev_ns16550_pci.c114
-rw-r--r--cfe/cfe/dev/dev_null.c142
-rw-r--r--cfe/cfe/dev/dev_promice.c402
-rw-r--r--cfe/cfe/dev/dev_sp1011.c151
-rw-r--r--cfe/cfe/dev/dev_tulip.c2985
-rw-r--r--cfe/cfe/dev/dp83815.h559
-rw-r--r--cfe/cfe/dev/ns16550.h143
-rw-r--r--cfe/cfe/dev/pci_devs.c79
-rw-r--r--cfe/cfe/hosttools/Makefile12
-rw-r--r--cfe/cfe/hosttools/README49
-rw-r--r--cfe/cfe/hosttools/installboot.c352
-rw-r--r--cfe/cfe/hosttools/makereg.c481
-rw-r--r--cfe/cfe/hosttools/memconfig.c654
-rw-r--r--cfe/cfe/hosttools/mkbootimage.c314
-rw-r--r--cfe/cfe/hosttools/mkflashimage.c347
-rw-r--r--cfe/cfe/hosttools/mkpcidb.c157
-rwxr-xr-xcfe/cfe/include/cfe.h101
-rw-r--r--cfe/cfe/include/cfe_autoboot.h71
-rw-r--r--cfe/cfe/include/cfe_boot.h58
-rw-r--r--cfe/cfe/include/cfe_bootblock.h129
-rwxr-xr-xcfe/cfe/include/cfe_console.h92
-rw-r--r--cfe/cfe/include/cfe_devfuncs.h76
-rw-r--r--cfe/cfe/include/cfe_device.h118
-rw-r--r--cfe/cfe/include/cfe_error.h110
-rw-r--r--cfe/cfe/include/cfe_fileops.h109
-rw-r--r--cfe/cfe/include/cfe_flashimage.h64
-rw-r--r--cfe/cfe/include/cfe_iocb.h211
-rw-r--r--cfe/cfe/include/cfe_ioctl.h167
-rw-r--r--cfe/cfe/include/cfe_irq.h103
-rw-r--r--cfe/cfe/include/cfe_loader.h86
-rw-r--r--cfe/cfe/include/cfe_mem.h79
-rw-r--r--cfe/cfe/include/cfe_timer.h74
-rw-r--r--cfe/cfe/include/cfe_xiocb.h202
-rw-r--r--cfe/cfe/include/dev_flash.h168
-rw-r--r--cfe/cfe/include/dev_ide.h90
-rw-r--r--cfe/cfe/include/dev_ide_common.h204
-rw-r--r--cfe/cfe/include/dev_newflash.h344
-rw-r--r--cfe/cfe/include/elf.h194
-rw-r--r--cfe/cfe/include/env_subr.h117
-rwxr-xr-xcfe/cfe/include/foxconnCfg.h9
-rw-r--r--cfe/cfe/include/lib_arena.h76
-rw-r--r--cfe/cfe/include/lib_malloc.h78
-rwxr-xr-xcfe/cfe/include/lib_printf.h69
-rw-r--r--cfe/cfe/include/lib_queue.h85
-rw-r--r--cfe/cfe/include/lib_string.h117
-rw-r--r--cfe/cfe/include/lib_types.h120
-rw-r--r--cfe/cfe/include/socregs.h63
-rwxr-xr-xcfe/cfe/include/tftpd.h26
-rw-r--r--cfe/cfe/include/ui_command.h140
-rw-r--r--cfe/cfe/lib/lib_arena.c389
-rw-r--r--cfe/cfe/lib/lib_malloc.c620
-rw-r--r--cfe/cfe/lib/lib_misc.c229
-rw-r--r--cfe/cfe/lib/lib_printf.c442
-rw-r--r--cfe/cfe/lib/lib_qsort.c88
-rw-r--r--cfe/cfe/lib/lib_queue.c219
-rw-r--r--cfe/cfe/lib/lib_string.c386
-rw-r--r--cfe/cfe/lib/lib_string2.c96
-rwxr-xr-xcfe/cfe/lzma/LzmaDecode.c584
-rwxr-xr-xcfe/cfe/lzma/LzmaDecode.h113
-rwxr-xr-xcfe/cfe/lzma/LzmaDecodeSize.c712
-rwxr-xr-xcfe/cfe/lzma/LzmaStateDecode.c521
-rwxr-xr-xcfe/cfe/lzma/LzmaStateDecode.h96
-rwxr-xr-xcfe/cfe/lzma/LzmaStateTest.c195
-rwxr-xr-xcfe/cfe/lzma/LzmaTest.c342
-rwxr-xr-xcfe/cfe/lzma/LzmaTypes.h45
-rwxr-xr-xcfe/cfe/lzma/Makefile5
-rwxr-xr-xcfe/cfe/lzma/dcapi.c50
-rw-r--r--cfe/cfe/main/cfe.mk301
-rw-r--r--cfe/cfe/main/cfe_attach.c265
-rw-r--r--cfe/cfe/main/cfe_autoboot.c456
-rw-r--r--cfe/cfe/main/cfe_background.c174
-rw-r--r--cfe/cfe/main/cfe_boot.c248
-rwxr-xr-xcfe/cfe/main/cfe_console.c1190
-rwxr-xr-xcfe/cfe/main/cfe_devfuncs.c279
-rw-r--r--cfe/cfe/main/cfe_error.c134
-rw-r--r--cfe/cfe/main/cfe_fatfs.c1983
-rwxr-xr-xcfe/cfe/main/cfe_filesys.c343
-rw-r--r--cfe/cfe/main/cfe_httpfs.c396
-rwxr-xr-xcfe/cfe/main/cfe_iocb_dispatch.c647
-rw-r--r--cfe/cfe/main/cfe_ldr_elf.c396
-rw-r--r--cfe/cfe/main/cfe_ldr_raw.c360
-rw-r--r--cfe/cfe/main/cfe_ldr_srec.c557
-rw-r--r--cfe/cfe/main/cfe_link.mk26
-rw-r--r--cfe/cfe/main/cfe_loader.c135
-rw-r--r--cfe/cfe/main/cfe_main.c636
-rw-r--r--cfe/cfe/main/cfe_mem.c256
-rw-r--r--cfe/cfe/main/cfe_rawfs.c293
-rw-r--r--cfe/cfe/main/cfe_savedata.c123
-rw-r--r--cfe/cfe/main/cfe_timer.c286
-rwxr-xr-xcfe/cfe/main/cfe_version.mk12
-rw-r--r--cfe/cfe/main/cfe_xreq.c346
-rw-r--r--cfe/cfe/main/cfe_zlibfs.c453
-rw-r--r--cfe/cfe/main/env_subr.c474
-rw-r--r--cfe/cfe/main/nvram_subr.c300
-rw-r--r--cfe/cfe/main/nvram_subr.h54
-rw-r--r--cfe/cfe/net/README17
-rw-r--r--cfe/cfe/net/dev_tcpconsole.c341
-rw-r--r--cfe/cfe/net/mii.h187
-rwxr-xr-xcfe/cfe/net/net_api.c1095
-rwxr-xr-xcfe/cfe/net/net_api.h179
-rwxr-xr-xcfe/cfe/net/net_arp.c865
-rw-r--r--cfe/cfe/net/net_dhcp.c869
-rwxr-xr-xcfe/cfe/net/net_dns.c354
-rw-r--r--cfe/cfe/net/net_ebuf.h165
-rw-r--r--cfe/cfe/net/net_ether.c705
-rw-r--r--cfe/cfe/net/net_ether.h89
-rw-r--r--cfe/cfe/net/net_icmp.c312
-rwxr-xr-xcfe/cfe/net/net_ip.c722
-rwxr-xr-xcfe/cfe/net/net_ip.h159
-rw-r--r--cfe/cfe/net/net_ip_internal.h128
-rwxr-xr-xcfe/cfe/net/net_nmrp.c656
-rwxr-xr-xcfe/cfe/net/net_nmrp.h1
-rwxr-xr-xcfe/cfe/net/net_tcp.c2215
-rwxr-xr-xcfe/cfe/net/net_tcp.h83
-rwxr-xr-xcfe/cfe/net/net_tcp_internal.h244
-rw-r--r--cfe/cfe/net/net_tcpbuf.c298
-rw-r--r--cfe/cfe/net/net_tcpbuf.h83
-rw-r--r--cfe/cfe/net/net_tftp.c921
-rw-r--r--cfe/cfe/net/net_udp.c637
-rw-r--r--cfe/cfe/pccons/Makefile3
-rw-r--r--cfe/cfe/pccons/README19
-rw-r--r--cfe/cfe/pccons/dev_pcconsole.c339
-rw-r--r--cfe/cfe/pccons/dev_pcconsole2.c298
-rw-r--r--cfe/cfe/pccons/kbd_subr.c371
-rw-r--r--cfe/cfe/pccons/kbd_subr.h82
-rw-r--r--cfe/cfe/pccons/pcibios.h72
-rw-r--r--cfe/cfe/pccons/vga.h76
-rw-r--r--cfe/cfe/pccons/vga_subr.c285
-rw-r--r--cfe/cfe/pccons/vga_subr.h82
-rw-r--r--cfe/cfe/pccons/vgainit.c1164
-rw-r--r--cfe/cfe/pccons/x86mem.c423
-rw-r--r--cfe/cfe/pccons/x86mem.h109
-rw-r--r--cfe/cfe/pci/cfe_pci.h52
-rw-r--r--cfe/cfe/pci/devlist2h.awk220
-rw-r--r--cfe/cfe/pci/ldtinit.c641
-rw-r--r--cfe/cfe/pci/ldtreg.h184
-rw-r--r--cfe/cfe/pci/pci_machdep.h35
-rw-r--r--cfe/cfe/pci/pci_subr.c710
-rw-r--r--cfe/cfe/pci/pciconf.c1296
-rw-r--r--cfe/cfe/pci/pcidevs1355
-rw-r--r--cfe/cfe/pci/pcidevs.h1360
-rw-r--r--cfe/cfe/pci/pcidevs_data.h5873
-rw-r--r--cfe/cfe/pci/pcireg.h615
-rw-r--r--cfe/cfe/pci/pcivar.h216
-rw-r--r--cfe/cfe/ui/ui_cmddisp.c252
-rw-r--r--cfe/cfe/ui/ui_command.c990
-rw-r--r--cfe/cfe/ui/ui_devcmds.c101
-rw-r--r--cfe/cfe/ui/ui_envcmds.c190
-rw-r--r--cfe/cfe/ui/ui_examcmds.c713
-rw-r--r--cfe/cfe/ui/ui_flash.c554
-rw-r--r--cfe/cfe/ui/ui_loadcmds.c366
-rw-r--r--cfe/cfe/ui/ui_memcmds.c171
-rw-r--r--cfe/cfe/ui/ui_misccmds.c178
-rw-r--r--cfe/cfe/ui/ui_netcmds.c710
-rw-r--r--cfe/cfe/ui/ui_pcicmds.c282
-rw-r--r--cfe/cfe/ui/ui_tcpcmds.c828
-rw-r--r--cfe/cfe/ui/ui_test_disk.c439
-rw-r--r--cfe/cfe/ui/ui_test_ether.c202
-rw-r--r--cfe/cfe/ui/ui_test_flash.c260
-rw-r--r--cfe/cfe/ui/ui_test_uart.c117
-rwxr-xr-xcfe/cfe/ui/ui_tftpd.c119
-rw-r--r--cfe/cfe/ui/ui_toyclock.c275
-rw-r--r--cfe/cfe/ui/url.c357
-rw-r--r--cfe/cfe/ui/url.h52
-rw-r--r--cfe/cfe/usb/Makefile8
-rw-r--r--cfe/cfe/usb/README183
-rw-r--r--cfe/cfe/usb/ohci.c2126
-rw-r--r--cfe/cfe/usb/ohci.h490
-rw-r--r--cfe/cfe/usb/usbchap9.h389
-rw-r--r--cfe/cfe/usb/usbd.c1215
-rw-r--r--cfe/cfe/usb/usbd.h308
-rw-r--r--cfe/cfe/usb/usbdebug.c307
-rw-r--r--cfe/cfe/usb/usbdevs.c168
-rw-r--r--cfe/cfe/usb/usbeth.c850
-rw-r--r--cfe/cfe/usb/usbeth.h112
-rw-r--r--cfe/cfe/usb/usbhack.c528
-rw-r--r--cfe/cfe/usb/usbhack.h66
-rw-r--r--cfe/cfe/usb/usbhack.mk23
-rw-r--r--cfe/cfe/usb/usbhid.c664
-rw-r--r--cfe/cfe/usb/usbhub.c912
-rw-r--r--cfe/cfe/usb/usbmain.c367
-rw-r--r--cfe/cfe/usb/usbmass.c1199
-rw-r--r--cfe/cfe/usb/usbserial.c713
-rw-r--r--cfe/cfe/vendor/Makefile2
-rw-r--r--cfe/cfe/vendor/cfe_vendor_cmds.c27
-rw-r--r--cfe/cfe/vendor/cfe_vendor_iocb.h87
-rw-r--r--cfe/cfe/vendor/cfe_vendor_iocb_dispatch.c179
-rw-r--r--cfe/cfe/vendor/cfe_vendor_xiocb.h91
-rw-r--r--cfe/cfe/vendor/cfe_vendor_xreq.c222
-rw-r--r--cfe/cfe/verif/Makefile7
-rw-r--r--cfe/cfe/verif/readme.txt342
-rw-r--r--cfe/cfe/verif/ui_vapi.c300
-rw-r--r--cfe/cfe/verif/vapi.S1150
-rw-r--r--cfe/cfe/verif/vapi.h242
-rw-r--r--cfe/cfe/verif/vapisubr.c122
-rw-r--r--cfe/cfe/verif/vapitest.S108
-rw-r--r--cfe/cfe/x86emu/LICENSE17
-rw-r--r--cfe/cfe/x86emu/Makefile2
-rw-r--r--cfe/cfe/x86emu/README12
-rw-r--r--cfe/cfe/x86emu/debug.c462
-rw-r--r--cfe/cfe/x86emu/decode.c1000
-rw-r--r--cfe/cfe/x86emu/fpu.c945
-rw-r--r--cfe/cfe/x86emu/ops.c11686
-rw-r--r--cfe/cfe/x86emu/ops2.c2802
-rw-r--r--cfe/cfe/x86emu/prim_ops.c2915
-rw-r--r--cfe/cfe/x86emu/sys.c603
-rw-r--r--cfe/cfe/x86emu/validate.c765
-rw-r--r--cfe/cfe/x86emu/x86emu.h198
-rw-r--r--cfe/cfe/x86emu/x86emu/debug.h212
-rw-r--r--cfe/cfe/x86emu/x86emu/decode.h87
-rw-r--r--cfe/cfe/x86emu/x86emu/fpu.h61
-rw-r--r--cfe/cfe/x86emu/x86emu/fpu_regs.h115
-rw-r--r--cfe/cfe/x86emu/x86emu/ops.h45
-rw-r--r--cfe/cfe/x86emu/x86emu/ops_protos.h277
-rw-r--r--cfe/cfe/x86emu/x86emu/prim_asm.h971
-rw-r--r--cfe/cfe/x86emu/x86emu/prim_ops.h231
-rw-r--r--cfe/cfe/x86emu/x86emu/regs.h351
-rw-r--r--cfe/cfe/x86emu/x86emu/types.h89
-rw-r--r--cfe/cfe/x86emu/x86emu/x86emui.h109
-rw-r--r--cfe/cfe/zlib/ChangeLog471
-rw-r--r--cfe/cfe/zlib/FAQ72
-rw-r--r--cfe/cfe/zlib/INDEX86
-rw-r--r--cfe/cfe/zlib/Make_vms.com115
-rw-r--r--cfe/cfe/zlib/Makefile28
-rw-r--r--cfe/cfe/zlib/Makefile.in174
-rw-r--r--cfe/cfe/zlib/Makefile.orig174
-rw-r--r--cfe/cfe/zlib/Makefile.riscos151
-rw-r--r--cfe/cfe/zlib/README148
-rw-r--r--cfe/cfe/zlib/adler32.c48
-rw-r--r--cfe/cfe/zlib/algorithm.txt213
-rw-r--r--cfe/cfe/zlib/compress.c68
-rwxr-xr-xcfe/cfe/zlib/configure212
-rw-r--r--cfe/cfe/zlib/crc32.c162
-rw-r--r--cfe/cfe/zlib/deflate.c1350
-rw-r--r--cfe/cfe/zlib/deflate.h318
-rw-r--r--cfe/cfe/zlib/descrip.mms48
-rw-r--r--cfe/cfe/zlib/example.c556
-rw-r--r--cfe/cfe/zlib/gzio.c875
-rw-r--r--cfe/cfe/zlib/infblock.c398
-rw-r--r--cfe/cfe/zlib/infblock.h39
-rw-r--r--cfe/cfe/zlib/infcodes.c257
-rw-r--r--cfe/cfe/zlib/infcodes.h27
-rw-r--r--cfe/cfe/zlib/inffast.c170
-rw-r--r--cfe/cfe/zlib/inffast.h17
-rw-r--r--cfe/cfe/zlib/inffixed.h151
-rw-r--r--cfe/cfe/zlib/inflate.c366
-rw-r--r--cfe/cfe/zlib/inftrees.c455
-rw-r--r--cfe/cfe/zlib/inftrees.h58
-rw-r--r--cfe/cfe/zlib/infutil.c87
-rw-r--r--cfe/cfe/zlib/infutil.h98
-rw-r--r--cfe/cfe/zlib/maketree.c85
-rw-r--r--cfe/cfe/zlib/minigzip.c320
-rw-r--r--cfe/cfe/zlib/trees.c1214
-rw-r--r--cfe/cfe/zlib/trees.h128
-rw-r--r--cfe/cfe/zlib/uncompr.c58
-rw-r--r--cfe/cfe/zlib/zconf.h279
-rw-r--r--cfe/cfe/zlib/zlib.3107
-rw-r--r--cfe/cfe/zlib/zlib.h893
-rw-r--r--cfe/cfe/zlib/zutil.c225
-rw-r--r--cfe/cfe/zlib/zutil.h220
-rwxr-xr-xcfe/docs/cfe.pdfbin0 -> 395677 bytes
372 files changed, 154644 insertions, 0 deletions
diff --git a/cfe/build/broadcom/bcm63xx_ram/Makefile b/cfe/build/broadcom/bcm63xx_ram/Makefile
new file mode 100755
index 0000000..970da8f
--- /dev/null
+++ b/cfe/build/broadcom/bcm63xx_ram/Makefile
@@ -0,0 +1,76 @@
+
+CFG_MLONG64 ?= 0
+CFG_LITTLE ?= 0 # Mindbender
+CFG_RELOC ?= 0
+CFG_UNCACHED ?= 0 # Mindbender
+CFG_NEWRELOC ?= 0
+CFG_VAPI ?= 0
+CFG_BOOTRAM ?= 0
+CFG_RAMAPP ?= 1
+CFG_BOARDNAME = "BCM9$(BRCM_CHIP)"
+CFG_PCI = 0
+CFG_ZLIB = 0 # enable zlib
+
+COMPRESS ?= cmplzma
+
+TOP = ../../../cfe
+ARCH = mips
+CPU = bcmcore
+BOARD = bcm63xx_ram
+
+HOSTTOOLS = ../../../../hostTools
+SHARED_DIR = ../../../../shared
+BOARDPARMS_DIR = $(SHARED_DIR)/opensource/boardparms/bcm963xx
+FLASH_DIR = $(SHARED_DIR)/opensource/flash
+BCMSPI_DIR = $(SHARED_DIR)/opensource/spi
+INC_SHARED_PUB_PATH = $(SHARED_DIR)/opensource/include/bcm963xx
+INC_SHARED_PRIV_PATH = $(SHARED_DIR)/broadcom/include/bcm963xx
+ROM_BUILD = ../bcm63xx_rom
+ASM_FILE =$(ROM_BUILD)/flashimg.S
+
+ifeq ($(strip $(CFG_SBP)),1)
+ CFLAGS += -DUSE_SINGLE_BOARD_PARAM
+endif
+
+include $(TOP)/arch/mips/board/$(BOARD)/src/ram_cfe.mk
+
+VPATH += ${ARCH_TOP}/board/$(BOARD)/src/html ${BOARDPARMS_DIR} $(BCMSPI_DIR) ${FLASH_DIR}
+INCDIRS += -I${INC_SHARED_PUB_PATH} -I${INC_SHARED_PRIV_PATH}
+
+$(HOSTTOOLS)/$(COMPRESS):
+ $(MAKE) -C $(HOSTTOOLS) build_cmplzma
+
+ALL: sanity_check $(HOSTTOOLS)/$(COMPRESS)
+ find $(SHARED_DIR) -name "*.o" -exec rm -f "{}" ";"
+ find $(BOARDPARMS_DIR) -name "*.o" -exec rm -f "{}" ";"
+ ${MAKE} cfe$(BRCM_CHIP)
+ $(HOSTTOOLS)/$(COMPRESS) -s -c -2 cfe$(BRCM_CHIP) cfe$(BRCM_CHIP).bin $(ASM_FILE)
+
+sanity_check:
+ @if [ "$(BRCM_CHIP)" = "" ]; then \
+ echo You must specify chip ID using 'gmake BRCM_CHIP=[6328|6362|6368|6816]'; exit 1; \
+ fi
+
+$(ASM_FILE): cfe$(BRCM_CHIP) cfe$(BRCM_CHIP).bin
+
+cfe$(BRCM_CHIP) cfe$(BRCM_CHIP).bin: $(CRT0OBJS) $(BSPOBJS) $(LIBCFE)
+ $(GLD) -o cfe$(BRCM_CHIP) -Map cfe$(BRCM_CHIP).map $(LDFLAGS) $(CRT0OBJS) $(BSPOBJS) -L. -lcfe $(LDLIBS)
+ $(OBJDUMP) -d cfe$(BRCM_CHIP) > cfe$(BRCM_CHIP).dis
+ $(OBJCOPY) --output-target=binary cfe$(BRCM_CHIP) cfe$(BRCM_CHIP).bin
+ifeq ($(strip $(INC_NAND_FLASH_DRIVER)),1)
+ printf "0: %08x%08x%08x" `$(OBJDUMP) -x cfe$(BRCM_CHIP) | sed -n -e "/start address/{s?start address ??p}" -e "/LOAD off/{s?^ *LOAD off.*vaddr ??; s? paddr .*??p}" -e "/ _end/{s? g.* _end??; s?^...?0x000?p}"` | xxd -r > cferamhdr.bin; \
+ cat cferamhdr.bin cfe$(BRCM_CHIP).bin > cfe$(BRCM_CHIP)ram.bin; \
+ rm cferamhdr.bin
+endif
+
+clean :
+ rm -f *.o *~ cfe*
+ rm -f build_date.c
+ rm -f libcfe.a
+ rm -f $(ASM_FILE)
+
+distclean : clean
+
+
+
+
diff --git a/cfe/build/broadcom/bcm63xx_rom/Makefile b/cfe/build/broadcom/bcm63xx_rom/Makefile
new file mode 100755
index 0000000..819cb21
--- /dev/null
+++ b/cfe/build/broadcom/bcm63xx_rom/Makefile
@@ -0,0 +1,160 @@
+
+CFG_MLONG64 ?= 0
+CFG_LITTLE ?= 0 # Mindbender
+CFG_RELOC ?= 0
+CFG_UNCACHED ?= 0 # Mindbender
+CFG_NEWRELOC ?= 0
+CFG_VAPI ?= 0
+CFG_BOOTRAM ?= 0
+CFG_RAMAPP ?= 0 # EPI
+CFG_BOARDNAME = "BCM9$(BRCM_CHIP)"
+CFG_PCI ?= 0
+CFG_ZLIB ?= 0 # enable zlib
+CFG_SBP ?= 0 # use Single Board Parameter if defined to 1
+
+TOP = ../../../cfe
+ARCH = mips
+CPU = bcmcore
+BOARD = bcm63xx_rom
+
+LINUX_KERNEL_DIR=../../../../kernel/linux
+HOSTTOOLS = ../../../../hostTools
+TARGETS_DIR = ../../../../targets
+SHARED_DIR = ../../../../shared
+INC_SHARED_PUB_PATH = $(SHARED_DIR)/opensource/include/bcm963xx
+INC_SHARED_PRIV_PATH = $(SHARED_DIR)/broadcom/include/bcm963xx
+FLASH_DIR = $(SHARED_DIR)/opensource/flash
+BCMSPI_DIR = $(SHARED_DIR)/opensource/spi
+
+BOOT_DIR = ${ARCH_TOP}/board/$(BOARD)/src
+ASM_FILE = flashimg.S
+RAM_BUILD = ../bcm63xx_ram
+
+TOOLS=../../../../uclibc-crosstools-gcc-4.4.2-1/usr/bin/mips-linux-
+
+include $(TOP)/arch/mips/board/$(BOARD)/src/rom_cfe.mk
+
+VPATH += ${FLASH_DIR} $(BCMSPI_DIR)
+INCDIRS += -I${ARCH_TOP}/board/bcm63xx_ram/include -I${INC_SHARED_PUB_PATH} -I${INC_SHARED_PRIV_PATH}
+
+BSPOBJS_ROM := $(BSPOBJS)
+ifneq ($(strip $(BRCM_IKOS)),y)
+BSPOBJS += flashimg.o $(LZMAOBJS)
+endif
+
+export INC_CFI_FLASH_DRIVER INC_SPI_FLASH_DRIVER INC_NAND_FLASH_DRIVER INC_SPI_PROG_NAND
+
+ALL : sanity_check cfe$(BRCM_CHIP)
+ifneq ($(strip $(INC_NAND_FLASH_DRIVER)),1)
+ gcc -o ${HOSTTOOLS}/addvtoken -I ${INC_SHARED_PUB_PATH} ${HOSTTOOLS}/addvtoken.c
+ @if [ $(shell find . -name cfe$(BRCM_CHIP).bin -printf '%s\n') -le 65536 ] ; then \
+ ${HOSTTOOLS}/addvtoken cfe$(BRCM_CHIP).bin bcm9$(BRCM_CHIP)_cfe.w; \
+ else \
+ find . -name cfe$(BRCM_CHIP).bin -printf '\nERROR: cfe.bin size, %s, is greater than 65536 maximum size.\n'; \
+ rm cfe$(BRCM_CHIP) cfe$(BRCM_CHIP).bin; \
+ fi
+endif
+ @echo done
+
+untar_check:
+ @if [ ! -e $(TOP)/api ]; then \
+ echo Untarring original CFE source...; \
+ (cd ../../.. && tar xfzk cfe*.tar.gz 2> /dev/null || true); \
+ fi
+
+sanity_check:
+ @if [ "$(BRCM_CHIP)" = "" ]; then \
+ echo You must specify chip ID using 'make BRCM_CHIP=[6328|6362|6368|6816]'; exit 1; \
+ fi
+ @if [ ! -e $(TOP)/api ]; then \
+ echo Untarring original CFE source...; \
+ (cd ../../.. && tar xfzk cfe*.tar.gz 2> /dev/null || true); \
+ $(MAKE) BRCM_CHIP=$(BRCM_CHIP) BLD_NAND=$(BLD_NAND); \
+ fi
+
+mksbp: ALL
+ @echo done
+
+sbp:
+ ${MAKE} clean
+ ${MAKE} CFG_SBP?=1 mksbp
+
+ifeq ($(strip $(INC_NAND_FLASH_DRIVER)),1)
+# Build NAND flash boot loader
+cfe$(BRCM_CHIP) cfe$(BRCM_CHIP).bin : $(CRT0OBJS) $(BSPOBJS_ROM) $(LIBCFE) noflashimg
+ $(MAKE) -C $(RAM_BUILD)
+ $(GLD) -o cfe$(BRCM_CHIP)rom -Map cfe$(BRCM_CHIP)rom.map $(LDFLAGS) $(CRT0OBJS) $(BSPOBJS_ROM) noflashimg.o -L. -lcfe $(LDLIBS)
+ $(OBJCOPY) --output-target=binary cfe$(BRCM_CHIP)rom cfe$(BRCM_CHIP)rom.bin
+ rm noflashimg.*
+
+noflashimg:
+ echo "char *_binArrayStart = (char *) 0, *_binArrayEnd = (char *) 0;" > $@.c; \
+ echo "int decompressLZMA(unsigned char *s, unsigned int sl, unsigned char *d, unsigned int dl);" >> $@.c; \
+ echo "int decompressLZMA(unsigned char *s, unsigned int sl, unsigned char *d, unsigned int dl){return 0;}" >> $@.c
+ $(GCC) $(CFLAGS) -o $@.o $@.c
+
+else
+# Build NOR flash boot loader
+cfe$(BRCM_CHIP) cfe$(BRCM_CHIP).bin : $(CRT0OBJS) $(BSPOBJS) $(LIBCFE) $(ASM_FILE)
+ $(GLD) -o cfe$(BRCM_CHIP) -Map cfe$(BRCM_CHIP).map $(LDFLAGS) $(CRT0OBJS) $(BSPOBJS) -L. -lcfe $(LDLIBS)
+ $(OBJDUMP) -d cfe$(BRCM_CHIP) > cfe$(BRCM_CHIP).dis
+ $(OBJCOPY) --output-target=binary cfe$(BRCM_CHIP) cfe$(BRCM_CHIP).bin
+
+$(ASM_FILE) : $(TOP)/arch/mips/board/bcm63xx_ram/src
+ rm -f $(ASM_FILE)
+ $(MAKE) -C $(RAM_BUILD)
+endif
+
+
+clean : untar_check
+ rm -f *.o *~ cfe* *.w *.srec
+ rm -f build_date.c
+ rm -f noflashimg.c >& /dev/null
+ rm -f libcfe.a
+ $(MAKE) -C $(RAM_BUILD) clean
+
+distclean : clean
+
+release : untar_check
+ $(MAKE) clean
+ $(MAKE) BRCM_CHIP=6328
+ cp -f cfe*.bin $(TARGETS_DIR)/cfe
+ $(MAKE) clean
+ $(MAKE) BRCM_CHIP=6328 BLD_NAND=1
+ cp -f cfe*.bin $(TARGETS_DIR)/cfe
+ cp -f $(RAM_BUILD)/cfe*ram.bin $(TARGETS_DIR)/cfe
+ $(MAKE) clean
+ $(MAKE) BRCM_CHIP=6362
+ cp -f cfe*.bin $(TARGETS_DIR)/cfe
+ $(MAKE) clean
+ $(MAKE) BRCM_CHIP=6362 BLD_NAND=1
+ cp -f cfe*.bin $(TARGETS_DIR)/cfe
+ cp -f $(RAM_BUILD)/cfe*ram.bin $(TARGETS_DIR)/cfe
+ $(MAKE) clean
+ $(MAKE) BRCM_CHIP=6368
+ cp -f cfe*.bin $(TARGETS_DIR)/cfe
+ $(MAKE) clean
+ $(MAKE) BRCM_CHIP=6368 BLD_NAND=1
+ cp -f cfe*.bin $(TARGETS_DIR)/cfe
+ cp -f $(RAM_BUILD)/cfe*ram.bin $(TARGETS_DIR)/cfe
+ $(MAKE) clean
+ $(MAKE) BRCM_CHIP=6816
+ cp -f cfe*.bin $(TARGETS_DIR)/cfe
+ $(MAKE) clean
+ $(MAKE) BRCM_CHIP=6816 BLD_NAND=1
+ cp -f cfe*.bin $(TARGETS_DIR)/cfe
+ cp -f $(RAM_BUILD)/cfe*ram.bin $(TARGETS_DIR)/cfe
+ $(MAKE) clean
+
+CFE_RAM_START_ADDR := $(OBJDUMP) -f $(RAM_BUILD)/cfe$(BRCM_CHIP) | grep start | cut -d'x' -f2
+VMLINUX_START_ADDR := $(OBJDUMP) -f $(LINUX_KERNEL_DIR)/vmlinux | grep start | cut -d'x' -f2
+
+# Must be called from base Linux build directory.
+ikos_finish:
+ @xxd -g4 cfe$(BRCM_CHIP) | sed -e "s/694b6f31/$(shell $(CFE_RAM_START_ADDR))/" | xxd -r > cfe$(BRCM_CHIP).tmp
+ @mv cfe$(BRCM_CHIP).tmp cfe$(BRCM_CHIP)
+ @xxd -g4 $(RAM_BUILD)/cfe$(BRCM_CHIP) | sed -e "s/694b6f32/$(shell $(VMLINUX_START_ADDR))/" | xxd -r > $(RAM_BUILD)/cfe$(BRCM_CHIP).tmp
+ @mv $(RAM_BUILD)/cfe$(BRCM_CHIP).tmp $(RAM_BUILD)/cfe$(BRCM_CHIP)
+ $(OBJCOPY) --output-target=binary cfe$(BRCM_CHIP) cfe$(BRCM_CHIP).bin
+ $(OBJCOPY) --output-target=srec $(RAM_BUILD)/cfe$(BRCM_CHIP) cferam$(BRCM_CHIP).srec
+
diff --git a/cfe/cfe/api/Makefile b/cfe/cfe/api/Makefile
new file mode 100644
index 0000000..9f2eb7c
--- /dev/null
+++ b/cfe/cfe/api/Makefile
@@ -0,0 +1,47 @@
+TOOLS_PREFIX = sb1-elf-
+CPPFLAGS = -I../include
+CFLAGS = -O2 -fomit-frame-pointer \
+ -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror
+
+CC = $(TOOLS_PREFIX)gcc
+AR = $(TOOLS_PREFIX)ar
+
+all: cfe_api.a cfe_api.o
+
+API_OBJS = \
+ api_close.o \
+ api_common.o \
+ api_cpu_start.o \
+ api_cpu_stop.o \
+ api_enumenv.o \
+ api_enummem.o \
+ api_exit.o \
+ api_flushcache.o \
+ api_getdevinfo.o \
+ api_getenv.o \
+ api_getfwinfo.o \
+ api_getstdhandle.o \
+ api_getticks.o \
+ api_inpstat.o \
+ api_ioctl.o \
+ api_open.o \
+ api_read.o \
+ api_readblk.o \
+ api_setenv.o \
+ api_strlen.o \
+ api_write.o \
+ api_writeblk.o
+
+cfe_api.a: $(API_OBJS)
+ $(AR) cru cfe_api.a $?
+
+$(API_OBJS): api_%.o: cfe_api.c Makefile cfe_api.h cfe_api_int.h
+ $(CC) -c -o $@ -DCFE_API_$* $(CPPFLAGS) $(CFLAGS) $<
+
+cfe_api.o: cfe_api.c Makefile cfe_api.h cfe_api_int.h
+ $(CC) -c -o $@ -DCFE_API_ALL $(CPPFLAGS) $(CFLAGS) $<
+
+.PHONY: clean
+
+clean:
+ rm -f *.o *.a *~
diff --git a/cfe/cfe/api/cfe_api.c b/cfe/cfe/api/cfe_api.c
new file mode 100644
index 0000000..70cb3d2
--- /dev/null
+++ b/cfe/cfe/api/cfe_api.c
@@ -0,0 +1,534 @@
+/* $Id: cfe_api.c,v 1.17 2003/02/07 17:27:56 cgd Exp $ */
+
+/*
+ * Copyright 2000, 2001, 2002
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and copied only
+ * in accordance with the following terms and conditions. Subject to these
+ * conditions, you may download, copy, install, use, modify and distribute
+ * modified or unmodified copies of this software in source and/or binary
+ * form. No title or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce and
+ * retain this copyright notice and list of conditions as they appear in
+ * the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or logo of
+ * Broadcom Corporation. The "Broadcom Corporation" name may not be
+ * used to endorse or promote products derived from this software
+ * without the prior written permission of Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE
+ * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE
+ * LIABLE FOR 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), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* *********************************************************************
+ *
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Device Function stubs File: cfe_api.c
+ *
+ * This module contains device function stubs (small routines to
+ * call the standard "iocb" interface entry point to CFE).
+ * There should be one routine here per iocb function call.
+ *
+ * Authors: Mitch Lichtenberg, Chris Demetriou
+ *
+ ********************************************************************* */
+
+#include "cfe_api.h"
+#include "cfe_api_int.h"
+
+/* Cast from a native pointer to a cfe_xptr_t and back. */
+#define XPTR_FROM_NATIVE(n) ((cfe_xptr_t) (intptr_t) (n))
+#define NATIVE_FROM_XPTR(x) ((void *) (intptr_t) (x))
+
+#ifdef CFE_API_IMPL_NAMESPACE
+#define cfe_iocb_dispatch(a) __cfe_iocb_dispatch(a)
+#endif
+int cfe_iocb_dispatch(cfe_xiocb_t *xiocb);
+
+#if defined(CFE_API_common) || defined(CFE_API_ALL)
+/*
+ * Declare the dispatch function with args of "intptr_t".
+ * This makes sure whatever model we're compiling in
+ * puts the pointers in a single register. For example,
+ * combining -mlong64 and -mips1 or -mips2 would lead to
+ * trouble, since the handle and IOCB pointer will be
+ * passed in two registers each, and CFE expects one.
+ */
+
+static int (*cfe_dispfunc)(intptr_t handle, intptr_t xiocb) = 0;
+static cfe_xuint_t cfe_handle = 0;
+
+int
+cfe_init(cfe_xuint_t handle, cfe_xuint_t ept)
+{
+ cfe_dispfunc = NATIVE_FROM_XPTR(ept);
+ cfe_handle = handle;
+ return 0;
+}
+
+int
+cfe_iocb_dispatch(cfe_xiocb_t *xiocb)
+{
+ if (!cfe_dispfunc) return -1;
+ return (*cfe_dispfunc)((intptr_t)cfe_handle, (intptr_t)xiocb);
+}
+#endif /* CFE_API_common || CFE_API_ALL */
+
+#if defined(CFE_API_close) || defined(CFE_API_ALL)
+int
+cfe_close(int handle)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_DEV_CLOSE;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = handle;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = 0;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.xiocb_status;
+
+}
+#endif /* CFE_API_close || CFE_API_ALL */
+
+#if defined(CFE_API_cpu_start) || defined(CFE_API_ALL)
+int
+cfe_cpu_start(int cpu, void (*fn)(void), long sp, long gp, long a1)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_cpuctl_t);
+ xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
+ xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_START;
+ xiocb.plist.xiocb_cpuctl.gp_val = gp;
+ xiocb.plist.xiocb_cpuctl.sp_val = sp;
+ xiocb.plist.xiocb_cpuctl.a1_val = a1;
+ xiocb.plist.xiocb_cpuctl.start_addr = (long)fn;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.xiocb_status;
+}
+#endif /* CFE_API_cpu_start || CFE_API_ALL */
+
+#if defined(CFE_API_cpu_stop) || defined(CFE_API_ALL)
+int
+cfe_cpu_stop(int cpu)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_cpuctl_t);
+ xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
+ xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_STOP;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.xiocb_status;
+}
+#endif /* CFE_API_cpu_stop || CFE_API_ALL */
+
+#if defined(CFE_API_enumenv) || defined(CFE_API_ALL)
+int
+cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
+ xiocb.plist.xiocb_envbuf.enum_idx = idx;
+ xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
+ xiocb.plist.xiocb_envbuf.name_length = namelen;
+ xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
+ xiocb.plist.xiocb_envbuf.val_length = vallen;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.xiocb_status;
+}
+#endif /* CFE_API_enumenv || CFE_API_ALL */
+
+#if defined(CFE_API_enummem) || defined(CFE_API_ALL)
+int
+cfe_enummem(int idx, int flags, cfe_xuint_t *start, cfe_xuint_t *length,
+ cfe_xuint_t *type)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_FW_MEMENUM;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = flags;
+ xiocb.xiocb_psize = sizeof(xiocb_meminfo_t);
+ xiocb.plist.xiocb_meminfo.mi_idx = idx;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (xiocb.xiocb_status < 0)
+ return xiocb.xiocb_status;
+
+ *start = xiocb.plist.xiocb_meminfo.mi_addr;
+ *length = xiocb.plist.xiocb_meminfo.mi_size;
+ *type = xiocb.plist.xiocb_meminfo.mi_type;
+
+ return 0;
+}
+#endif /* CFE_API_enummem || CFE_API_ALL */
+
+#if defined(CFE_API_exit) || defined(CFE_API_ALL)
+int
+cfe_exit(int warm, int status)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_FW_RESTART;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = warm ? CFE_FLG_WARMSTART : 0;
+ xiocb.xiocb_psize = sizeof(xiocb_exitstat_t);
+ xiocb.plist.xiocb_exitstat.status = status;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.xiocb_status;
+}
+#endif /* CFE_API_exit || CFE_API_ALL */
+
+#if defined(CFE_API_flushcache) || defined(CFE_API_ALL)
+int
+cfe_flushcache(int flg)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_FW_FLUSHCACHE;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = flg;
+ xiocb.xiocb_psize = 0;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.xiocb_status;
+}
+#endif /* CFE_API_flushcache || CFE_API_ALL */
+
+#if defined(CFE_API_getdevinfo) || defined(CFE_API_ALL)
+int
+cfe_getdevinfo(char *name)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_DEV_GETINFO;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
+ xiocb.plist.xiocb_buffer.buf_offset = 0;
+ xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
+ xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name);
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (xiocb.xiocb_status < 0)
+ return xiocb.xiocb_status;
+ return xiocb.plist.xiocb_buffer.buf_devflags;
+}
+#endif /* CFE_API_getdevinfo || CFE_API_ALL */
+
+#if defined(CFE_API_getenv) || defined(CFE_API_ALL)
+int
+cfe_getenv(char *name, char *dest, int destlen)
+{
+ cfe_xiocb_t xiocb;
+
+ *dest = 0;
+
+ xiocb.xiocb_fcode = CFE_CMD_ENV_GET;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
+ xiocb.plist.xiocb_envbuf.enum_idx = 0;
+ xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
+ xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name);
+ xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(dest);
+ xiocb.plist.xiocb_envbuf.val_length = destlen;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.xiocb_status;
+}
+#endif /* CFE_API_getenv || CFE_API_ALL */
+
+#if defined(CFE_API_getfwinfo) || defined(CFE_API_ALL)
+int
+cfe_getfwinfo(cfe_fwinfo_t *info)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_FW_GETINFO;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_fwinfo_t);
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (xiocb.xiocb_status < 0)
+ return xiocb.xiocb_status;
+
+ info->fwi_version = xiocb.plist.xiocb_fwinfo.fwi_version;
+ info->fwi_totalmem = xiocb.plist.xiocb_fwinfo.fwi_totalmem;
+ info->fwi_flags = xiocb.plist.xiocb_fwinfo.fwi_flags;
+ info->fwi_boardid = xiocb.plist.xiocb_fwinfo.fwi_boardid;
+ info->fwi_bootarea_va = xiocb.plist.xiocb_fwinfo.fwi_bootarea_va;
+ info->fwi_bootarea_pa = xiocb.plist.xiocb_fwinfo.fwi_bootarea_pa;
+ info->fwi_bootarea_size = xiocb.plist.xiocb_fwinfo.fwi_bootarea_size;
+#if 0
+ info->fwi_reserved1 = xiocb.plist.xiocb_fwinfo.fwi_reserved1;
+ info->fwi_reserved2 = xiocb.plist.xiocb_fwinfo.fwi_reserved2;
+ info->fwi_reserved3 = xiocb.plist.xiocb_fwinfo.fwi_reserved3;
+#endif
+
+ return 0;
+}
+#endif /* CFE_API_getfwinfo || CFE_API_ALL */
+
+#if defined(CFE_API_getstdhandle) || defined(CFE_API_ALL)
+int
+cfe_getstdhandle(int flg)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = flg;
+ xiocb.xiocb_psize = 0;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (xiocb.xiocb_status < 0)
+ return xiocb.xiocb_status;
+ return xiocb.xiocb_handle;
+
+}
+#endif /* CFE_API_getstdhandle || CFE_API_ALL */
+
+#if defined(CFE_API_getticks) || defined(CFE_API_ALL)
+int64_t
+#ifdef CFE_API_IMPL_NAMESPACE
+__cfe_getticks(void)
+#else
+cfe_getticks(void)
+#endif
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_time_t);
+ xiocb.plist.xiocb_time.ticks = 0;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.plist.xiocb_time.ticks;
+
+}
+#endif /* CFE_API_getticks || CFE_API_ALL */
+
+#if defined(CFE_API_inpstat) || defined(CFE_API_ALL)
+int
+cfe_inpstat(int handle)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = handle;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_inpstat_t);
+ xiocb.plist.xiocb_inpstat.inp_status = 0;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (xiocb.xiocb_status < 0)
+ return xiocb.xiocb_status;
+ return xiocb.plist.xiocb_inpstat.inp_status;
+
+}
+#endif /* CFE_API_inpstat || CFE_API_ALL */
+
+#if defined(CFE_API_ioctl) || defined(CFE_API_ALL)
+int
+cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer, int length,
+ int *retlen, cfe_xuint_t offset)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = handle;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
+ xiocb.plist.xiocb_buffer.buf_offset = offset;
+ xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum;
+ xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
+ xiocb.plist.xiocb_buffer.buf_length = length;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (retlen)
+ *retlen = xiocb.plist.xiocb_buffer.buf_retlen;
+ return xiocb.xiocb_status;
+}
+#endif /* CFE_API_ioctl || CFE_API_ALL */
+
+#if defined(CFE_API_open) || defined(CFE_API_ALL)
+int
+cfe_open(char *name)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
+ xiocb.plist.xiocb_buffer.buf_offset = 0;
+ xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
+ xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name);
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (xiocb.xiocb_status < 0)
+ return xiocb.xiocb_status;
+ return xiocb.xiocb_handle;
+}
+#endif /* CFE_API_open || CFE_API_ALL */
+
+#if defined(CFE_API_read) || defined(CFE_API_ALL)
+int
+cfe_read(int handle, unsigned char *buffer, int length)
+{
+ return cfe_readblk(handle, 0, buffer, length);
+}
+#endif /* CFE_API_read || CFE_API_ALL */
+
+#if defined(CFE_API_readblk) || defined(CFE_API_ALL)
+int
+cfe_readblk(int handle, cfe_xint_t offset, unsigned char *buffer, int length)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_DEV_READ;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = handle;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
+ xiocb.plist.xiocb_buffer.buf_offset = offset;
+ xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
+ xiocb.plist.xiocb_buffer.buf_length = length;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (xiocb.xiocb_status < 0)
+ return xiocb.xiocb_status;
+ return xiocb.plist.xiocb_buffer.buf_retlen;
+}
+#endif /* CFE_API_readblk || CFE_API_ALL */
+
+#if defined(CFE_API_setenv) || defined(CFE_API_ALL)
+int
+cfe_setenv(char *name, char *val)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
+ xiocb.plist.xiocb_envbuf.enum_idx = 0;
+ xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
+ xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name);
+ xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
+ xiocb.plist.xiocb_envbuf.val_length = cfe_strlen(val);
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.xiocb_status;
+}
+#endif /* CFE_API_setenv || CFE_API_ALL */
+
+#if (defined(CFE_API_strlen) || defined(CFE_API_ALL)) \
+ && !defined(CFE_API_STRLEN_CUSTOM)
+int
+cfe_strlen(char *name)
+{
+ int count = 0;
+
+ while (*name++)
+ count++;
+
+ return count;
+}
+#endif /* CFE_API_strlen || CFE_API_ALL */
+
+#if defined(CFE_API_write) || defined(CFE_API_ALL)
+int
+cfe_write(int handle, unsigned char *buffer, int length)
+{
+ return cfe_writeblk(handle, 0, buffer, length);
+}
+#endif /* CFE_API_write || CFE_API_ALL */
+
+#if defined(CFE_API_writeblk) || defined(CFE_API_ALL)
+int
+cfe_writeblk(int handle, cfe_xint_t offset, unsigned char *buffer, int length)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = handle;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
+ xiocb.plist.xiocb_buffer.buf_offset = offset;
+ xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
+ xiocb.plist.xiocb_buffer.buf_length = length;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (xiocb.xiocb_status < 0)
+ return xiocb.xiocb_status;
+ return xiocb.plist.xiocb_buffer.buf_retlen;
+}
+#endif /* CFE_API_writeblk || CFE_API_ALL */
diff --git a/cfe/cfe/api/cfe_api.h b/cfe/cfe/api/cfe_api.h
new file mode 100644
index 0000000..ea598f0
--- /dev/null
+++ b/cfe/cfe/api/cfe_api.h
@@ -0,0 +1,192 @@
+/* $Id: cfe_api.h,v 1.30 2003/02/07 17:27:56 cgd Exp $ */
+
+/*
+ * Copyright 2000, 2001, 2002
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and copied only
+ * in accordance with the following terms and conditions. Subject to these
+ * conditions, you may download, copy, install, use, modify and distribute
+ * modified or unmodified copies of this software in source and/or binary
+ * form. No title or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce and
+ * retain this copyright notice and list of conditions as they appear in
+ * the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or logo of
+ * Broadcom Corporation. The "Broadcom Corporation" name may not be
+ * used to endorse or promote products derived from this software
+ * without the prior written permission of Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE
+ * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE
+ * LIABLE FOR 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), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* *********************************************************************
+ *
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Device function prototypes File: cfe_api.h
+ *
+ * This file contains declarations for doing callbacks to
+ * cfe from an application. It should be the only header
+ * needed by the application to use this library
+ *
+ * Authors: Mitch Lichtenberg, Chris Demetriou
+ *
+ ********************************************************************* */
+
+#ifndef CFE_API_H
+#define CFE_API_H
+
+/*
+ * Apply customizations here for different OSes. These need to:
+ * * typedef uint64_t, int64_t, intptr_t, uintptr_t.
+ * * define cfe_strlen() if use of an existing function is desired.
+ * * define CFE_API_IMPL_NAMESPACE if API functions are to use
+ * names in the implementation namespace.
+ * Also, optionally, if the build environment does not do so automatically,
+ * CFE_API_* can be defined here as desired.
+ */
+/* Begin customization. */
+#include "lib_types.h"
+/* End customization. */
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+/* Seal indicating CFE's presence, passed to user program. */
+#define CFE_EPTSEAL 0x43464531
+
+#define CFE_MI_RESERVED 0 /* memory is reserved, do not use */
+#define CFE_MI_AVAILABLE 1 /* memory is available */
+
+#define CFE_FLG_WARMSTART 0x00000001
+#define CFE_FLG_FULL_ARENA 0x00000001
+#define CFE_FLG_ENV_PERMANENT 0x00000001
+
+#define CFE_CPU_CMD_START 1
+#define CFE_CPU_CMD_STOP 0
+
+#define CFE_STDHANDLE_CONSOLE 0
+
+#define CFE_DEV_NETWORK 1
+#define CFE_DEV_DISK 2
+#define CFE_DEV_FLASH 3
+#define CFE_DEV_SERIAL 4
+#define CFE_DEV_CPU 5
+#define CFE_DEV_NVRAM 6
+#define CFE_DEV_CLOCK 7
+#define CFE_DEV_OTHER 8
+#define CFE_DEV_MASK 0x0F
+
+#define CFE_CACHE_FLUSH_D 1
+#define CFE_CACHE_INVAL_I 2
+#define CFE_CACHE_INVAL_D 4
+#define CFE_CACHE_INVAL_L2 8
+
+#define CFE_FWI_64BIT 0x00000001
+#define CFE_FWI_32BIT 0x00000002
+#define CFE_FWI_RELOC 0x00000004
+#define CFE_FWI_UNCACHED 0x00000008
+#define CFE_FWI_MULTICPU 0x00000010
+#define CFE_FWI_FUNCSIM 0x00000020
+#define CFE_FWI_RTLSIM 0x00000040
+
+typedef struct {
+ int64_t fwi_version; /* major, minor, eco version */
+ int64_t fwi_totalmem; /* total installed mem */
+ int64_t fwi_flags; /* various flags */
+ int64_t fwi_boardid; /* board ID */
+ int64_t fwi_bootarea_va; /* VA of boot area */
+ int64_t fwi_bootarea_pa; /* PA of boot area */
+ int64_t fwi_bootarea_size; /* size of boot area */
+} cfe_fwinfo_t;
+
+
+/*
+ * cfe_strlen is handled specially: If already defined, it has been
+ * overridden in this environment with a standard strlen-like function.
+ */
+#ifdef cfe_strlen
+# define CFE_API_STRLEN_CUSTOM
+#else
+# ifdef CFE_API_IMPL_NAMESPACE
+# define cfe_strlen(a) __cfe_strlen(a)
+# endif
+int cfe_strlen(char *name);
+#endif
+
+/*
+ * Defines and prototypes for functions which take no arguments.
+ */
+#ifdef CFE_API_IMPL_NAMESPACE
+int64_t __cfe_getticks(void);
+#define cfe_getticks() __cfe_getticks()
+#else
+int64_t cfe_getticks(void);
+#endif
+
+/*
+ * Defines and prototypes for the rest of the functions.
+ */
+#ifdef CFE_API_IMPL_NAMESPACE
+#define cfe_close(a) __cfe_close(a)
+#define cfe_cpu_start(a,b,c,d,e) __cfe_cpu_start(a,b,c,d,e)
+#define cfe_cpu_stop(a) __cfe_cpu_stop(a)
+#define cfe_enumenv(a,b,d,e,f) __cfe_enumenv(a,b,d,e,f)
+#define cfe_enummem(a,b,c,d,e) __cfe_enummem(a,b,c,d,e)
+#define cfe_exit(a,b) __cfe_exit(a,b)
+#define cfe_flushcache(a) __cfe_cacheflush(a)
+#define cfe_getdevinfo(a) __cfe_getdevinfo(a)
+#define cfe_getenv(a,b,c) __cfe_getenv(a,b,c)
+#define cfe_getfwinfo(a) __cfe_getfwinfo(a)
+#define cfe_getstdhandle(a) __cfe_getstdhandle(a)
+#define cfe_init(a,b) __cfe_init(a,b)
+#define cfe_inpstat(a) __cfe_inpstat(a)
+#define cfe_ioctl(a,b,c,d,e,f) __cfe_ioctl(a,b,c,d,e,f)
+#define cfe_open(a) __cfe_open(a)
+#define cfe_read(a,b,c) __cfe_read(a,b,c)
+#define cfe_readblk(a,b,c,d) __cfe_readblk(a,b,c,d)
+#define cfe_setenv(a,b) __cfe_setenv(a,b)
+#define cfe_write(a,b,c) __cfe_write(a,b,c)
+#define cfe_writeblk(a,b,c,d) __cfe_writeblk(a,b,c,d)
+#endif /* CFE_API_IMPL_NAMESPACE */
+
+int cfe_close(int handle);
+int cfe_cpu_start(int cpu, void (*fn)(void), long sp, long gp, long a1);
+int cfe_cpu_stop(int cpu);
+int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen);
+int cfe_enummem(int idx, int flags, uint64_t *start, uint64_t *length,
+ uint64_t *type);
+int cfe_exit(int warm,int status);
+int cfe_flushcache(int flg);
+int cfe_getdevinfo(char *name);
+int cfe_getenv(char *name, char *dest, int destlen);
+int cfe_getfwinfo(cfe_fwinfo_t *info);
+int cfe_getstdhandle(int flg);
+int cfe_init(uint64_t handle,uint64_t ept);
+int cfe_inpstat(int handle);
+int cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer,
+ int length, int *retlen, uint64_t offset);
+int cfe_open(char *name);
+int cfe_read(int handle, unsigned char *buffer, int length);
+int cfe_readblk(int handle, int64_t offset, unsigned char *buffer, int length);
+int cfe_setenv(char *name, char *val);
+int cfe_write(int handle, unsigned char *buffer, int length);
+int cfe_writeblk(int handle, int64_t offset, unsigned char *buffer,
+ int length);
+
+#endif /* CFE_API_H */
diff --git a/cfe/cfe/api/cfe_api_int.h b/cfe/cfe/api/cfe_api_int.h
new file mode 100644
index 0000000..4bac86d
--- /dev/null
+++ b/cfe/cfe/api/cfe_api_int.h
@@ -0,0 +1,168 @@
+/* $Id: cfe_api_int.h,v 1.22 2003/02/07 17:27:56 cgd Exp $ */
+
+/*
+ * Copyright 2000, 2001, 2002
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and copied only
+ * in accordance with the following terms and conditions. Subject to these
+ * conditions, you may download, copy, install, use, modify and distribute
+ * modified or unmodified copies of this software in source and/or binary
+ * form. No title or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce and
+ * retain this copyright notice and list of conditions as they appear in
+ * the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or logo of
+ * Broadcom Corporation. The "Broadcom Corporation" name may not be
+ * used to endorse or promote products derived from this software
+ * without the prior written permission of Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE
+ * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE
+ * LIABLE FOR 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), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* *********************************************************************
+ *
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Device function prototypes File: cfe_api_int.h
+ *
+ * This header defines all internal types and macros for the
+ * library. This is stuff that's not exported to an app
+ * using the library.
+ *
+ * Authors: Mitch Lichtenberg, Chris Demetriou
+ *
+ ********************************************************************* */
+
+#ifndef CFE_API_INT_H
+#define CFE_API_INT_H
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define CFE_CMD_FW_GETINFO 0
+#define CFE_CMD_FW_RESTART 1
+#define CFE_CMD_FW_BOOT 2
+#define CFE_CMD_FW_CPUCTL 3
+#define CFE_CMD_FW_GETTIME 4
+#define CFE_CMD_FW_MEMENUM 5
+#define CFE_CMD_FW_FLUSHCACHE 6
+
+#define CFE_CMD_DEV_GETHANDLE 9
+#define CFE_CMD_DEV_ENUM 10
+#define CFE_CMD_DEV_OPEN 11
+#define CFE_CMD_DEV_INPSTAT 12
+#define CFE_CMD_DEV_READ 13
+#define CFE_CMD_DEV_WRITE 14
+#define CFE_CMD_DEV_IOCTL 15
+#define CFE_CMD_DEV_CLOSE 16
+#define CFE_CMD_DEV_GETINFO 17
+
+#define CFE_CMD_ENV_ENUM 20
+#define CFE_CMD_ENV_GET 22
+#define CFE_CMD_ENV_SET 23
+#define CFE_CMD_ENV_DEL 24
+
+#define CFE_CMD_MAX 32
+
+#define CFE_CMD_VENDOR_USE 0x8000 /* codes above this are for customer use */
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef uint64_t cfe_xuint_t;
+typedef int64_t cfe_xint_t;
+typedef int64_t cfe_xptr_t;
+
+typedef struct xiocb_buffer_s {
+ cfe_xuint_t buf_offset; /* offset on device (bytes) */
+ cfe_xptr_t buf_ptr; /* pointer to a buffer */
+ cfe_xuint_t buf_length; /* length of this buffer */
+ cfe_xuint_t buf_retlen; /* returned length (for read ops) */
+ cfe_xuint_t buf_ioctlcmd; /* IOCTL command (used only for IOCTLs) */
+} xiocb_buffer_t;
+
+#define buf_devflags buf_ioctlcmd /* returned device info flags */
+
+typedef struct xiocb_inpstat_s {
+ cfe_xuint_t inp_status; /* 1 means input available */
+} xiocb_inpstat_t;
+
+typedef struct xiocb_envbuf_s {
+ cfe_xint_t enum_idx; /* 0-based enumeration index */
+ cfe_xptr_t name_ptr; /* name string buffer */
+ cfe_xint_t name_length; /* size of name buffer */
+ cfe_xptr_t val_ptr; /* value string buffer */
+ cfe_xint_t val_length; /* size of value string buffer */
+} xiocb_envbuf_t;
+
+typedef struct xiocb_cpuctl_s {
+ cfe_xuint_t cpu_number; /* cpu number to control */
+ cfe_xuint_t cpu_command; /* command to issue to CPU */
+ cfe_xuint_t start_addr; /* CPU start address */
+ cfe_xuint_t gp_val; /* starting GP value */
+ cfe_xuint_t sp_val; /* starting SP value */
+ cfe_xuint_t a1_val; /* starting A1 value */
+} xiocb_cpuctl_t;
+
+typedef struct xiocb_time_s {
+ cfe_xint_t ticks; /* current time in ticks */
+} xiocb_time_t;
+
+typedef struct xiocb_exitstat_s {
+ cfe_xint_t status;
+} xiocb_exitstat_t;
+
+typedef struct xiocb_meminfo_s {
+ cfe_xint_t mi_idx; /* 0-based enumeration index */
+ cfe_xint_t mi_type; /* type of memory block */
+ cfe_xuint_t mi_addr; /* physical start address */
+ cfe_xuint_t mi_size; /* block size */
+} xiocb_meminfo_t;
+
+typedef struct xiocb_fwinfo_s {
+ cfe_xint_t fwi_version; /* major, minor, eco version */
+ cfe_xint_t fwi_totalmem; /* total installed mem */
+ cfe_xint_t fwi_flags; /* various flags */
+ cfe_xint_t fwi_boardid; /* board ID */
+ cfe_xint_t fwi_bootarea_va; /* VA of boot area */
+ cfe_xint_t fwi_bootarea_pa; /* PA of boot area */
+ cfe_xint_t fwi_bootarea_size; /* size of boot area */
+ cfe_xint_t fwi_reserved1;
+ cfe_xint_t fwi_reserved2;
+ cfe_xint_t fwi_reserved3;
+} xiocb_fwinfo_t;
+
+typedef struct cfe_xiocb_s {
+ cfe_xuint_t xiocb_fcode; /* IOCB function code */
+ cfe_xint_t xiocb_status; /* return status */
+ cfe_xint_t xiocb_handle; /* file/device handle */
+ cfe_xuint_t xiocb_flags; /* flags for this IOCB */
+ cfe_xuint_t xiocb_psize; /* size of parameter list */
+ union {
+ xiocb_buffer_t xiocb_buffer; /* buffer parameters */
+ xiocb_inpstat_t xiocb_inpstat; /* input status parameters */
+ xiocb_envbuf_t xiocb_envbuf; /* environment function parameters */
+ xiocb_cpuctl_t xiocb_cpuctl; /* CPU control parameters */
+ xiocb_time_t xiocb_time; /* timer parameters */
+ xiocb_meminfo_t xiocb_meminfo; /* memory arena info parameters */
+ xiocb_fwinfo_t xiocb_fwinfo; /* firmware information */
+ xiocb_exitstat_t xiocb_exitstat; /* Exit Status */
+ } plist;
+} cfe_xiocb_t;
+
+#endif /* CFE_API_INT_H */
diff --git a/cfe/cfe/api/cfe_error.h b/cfe/cfe/api/cfe_error.h
new file mode 100644
index 0000000..6301c56
--- /dev/null
+++ b/cfe/cfe/api/cfe_error.h
@@ -0,0 +1,101 @@
+/* $Id: cfe_error.h,v 1.3 2003/02/07 17:27:56 cgd Exp $ */
+
+/*
+ * Copyright 2000, 2001, 2002
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and copied only
+ * in accordance with the following terms and conditions. Subject to these
+ * conditions, you may download, copy, install, use, modify and distribute
+ * modified or unmodified copies of this software in source and/or binary
+ * form. No title or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce and
+ * retain this copyright notice and list of conditions as they appear in
+ * the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or logo of
+ * Broadcom Corporation. The "Broadcom Corporation" name may not be
+ * used to endorse or promote products derived from this software
+ * without the prior written permission of Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE
+ * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE
+ * LIABLE FOR 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), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* *********************************************************************
+ *
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Error codes File: cfe_error.h
+ *
+ * CFE's global error code list is here.
+ *
+ * Author: Mitch Lichtenberg
+ *
+ ********************************************************************* */
+
+
+#define CFE_OK 0
+#define CFE_ERR -1 /* generic error */
+#define CFE_ERR_INV_COMMAND -2
+#define CFE_ERR_EOF -3
+#define CFE_ERR_IOERR -4
+#define CFE_ERR_NOMEM -5
+#define CFE_ERR_DEVNOTFOUND -6
+#define CFE_ERR_DEVOPEN -7
+#define CFE_ERR_INV_PARAM -8
+#define CFE_ERR_ENVNOTFOUND -9
+#define CFE_ERR_ENVREADONLY -10
+
+#define CFE_ERR_NOTELF -11
+#define CFE_ERR_NOT32BIT -12
+#define CFE_ERR_WRONGENDIAN -13
+#define CFE_ERR_BADELFVERS -14
+#define CFE_ERR_NOTMIPS -15
+#define CFE_ERR_BADELFFMT -16
+#define CFE_ERR_BADADDR -17
+
+#define CFE_ERR_FILENOTFOUND -18
+#define CFE_ERR_UNSUPPORTED -19
+
+#define CFE_ERR_HOSTUNKNOWN -20
+
+#define CFE_ERR_TIMEOUT -21
+
+#define CFE_ERR_PROTOCOLERR -22
+
+#define CFE_ERR_NETDOWN -23
+#define CFE_ERR_NONAMESERVER -24
+
+#define CFE_ERR_NOHANDLES -25
+#define CFE_ERR_ALREADYBOUND -26
+
+#define CFE_ERR_CANNOTSET -27
+#define CFE_ERR_NOMORE -28
+#define CFE_ERR_BADFILESYS -29
+#define CFE_ERR_FSNOTAVAIL -30
+
+#define CFE_ERR_INVBOOTBLOCK -31
+#define CFE_ERR_WRONGDEVTYPE -32
+#define CFE_ERR_BBCHECKSUM -33
+#define CFE_ERR_BOOTPROGCHKSUM -34
+
+#define CFE_ERR_LDRNOTAVAIL -35
+
+#define CFE_ERR_NOTREADY -36
+
+#define CFE_ERR_GETMEM -37
+#define CFE_ERR_SETMEM -38
+
+#define CFE_ERR_NOTCONN -39
+#define CFE_ERR_ADDRINUSE -40
diff --git a/cfe/cfe/applets/Makefile b/cfe/cfe/applets/Makefile
new file mode 100644
index 0000000..42e1e4f
--- /dev/null
+++ b/cfe/cfe/applets/Makefile
@@ -0,0 +1,64 @@
+
+CFG_MLONG64=0
+
+CFE_DIRS = ../include ../arch/mips/cpu/sb1250/include ../lib ../verif ../api
+CFE_INCLUDES = $(patsubst %,-I%,$(subst :, ,$(CFE_DIRS)))
+
+VPATH = $(CFE_DIRS)
+
+INCLUDES = -I. $(CFE_INCLUDES)
+COMFLAGS = -g -c -mcpu=sb1 -ffreestanding
+CFLAGS = $(INCLUDES) $(COMFLAGS) -O -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -G 0 -DCFE_API_ALL
+
+GCC = $(TOOLS)sb1-elf-gcc
+GLD = $(TOOLS)sb1-elf-ld
+OBJCOPY = $(TOOLS)sb1-elf-objcopy
+
+ifeq (${CFG_MLONG64},1)
+CFLAGS += -mlong64 -D__long64
+endif
+
+LDFLAGS = --script cfe_applet.lds -g
+
+ifeq (CFG_LITTLE,1)
+CFLAGS += -EL
+LDFLAGS += -EL
+else
+CFLAGS += -EB
+LDFLAGS += -EB
+endif
+
+
+%.o : %.c
+ $(GCC) $(CFLAGS) -o $@ $<
+
+%.o : %.S
+ $(GCC) $(CFLAGS) -o $@ $<
+
+
+LIBOBJS = lib_printf.o lib_string.o cfe_api.o
+
+all : test vapitest
+ echo done
+
+test : test.o minicrt0.o $(LIBOBJS)
+ $(GLD) -o test.elfraw -Map test.mapraw $(LDFLAGS) minicrt0.o test.o $(LIBOBJS)
+ $(GLD) -o test.elf -Ttext 0x20000000 -Map test.map $(LDFLAGS) minicrt0.o test.o $(LIBOBJS)
+ $(OBJCOPY) -O binary test.elfraw test
+ $(OBJCOPY) -O srec test.elfraw test.srec
+
+download : download.o minicrt0.o $(LIBOBJS)
+ $(GLD) -o download.elf -Ttext 0x80001000 -Map download.map $(LDFLAGS) minicrt0.o download.o $(LIBOBJS)
+ $(OBJCOPY) --strip-unneeded download.elf s.download.elf
+ gzip --best -c s.download.elf > download.elf.gz
+ $(GLD) -Tdownload.lds -bbinary -o download.data download.elf.gz
+
+vapitest : vapitest.o
+ $(GLD) -o vapitest -Ttext 0x80020000 -Map vapitest.map vapitest.o
+ $(OBJCOPY) -O srec vapitest vapitest.srec
+
+clean :
+ rm -f *.o *~ *.map *.mapraw
+ rm -f test test.elf test.srec test.elfraw
+ rm -f *download.elf *.gz
+ rm -f vapitest vapitest.srec
diff --git a/cfe/cfe/applets/README b/cfe/cfe/applets/README
new file mode 100644
index 0000000..b622997
--- /dev/null
+++ b/cfe/cfe/applets/README
@@ -0,0 +1,21 @@
+
+This directory contains "applets" - simple programs to let
+us test the callbacks into CFE.
+
+You should be able to compile these programs and load them
+via the TFTP loader in CFE, and when run, they will call
+the APIs in CFE to display messages and such.
+
+The files cfe_api.c, cfe_api.h, and cfe_api_int.h are versions
+of the same files from ../applets, customized to build with this
+stand-alone build environment. Typically you won't want to copy
+these. Instead, you'll want to copy the versions in ../applets and
+customize them as needed.
+
+Pay particular attention to the MIPS calling conventions
+you are using. In particular, CFE uses 64-bit register
+values. If you compile your program with -mips1 or -mips2,
+the 64-bit arguments will be passed as 2 32-bt registers.
+
+In most cases, CFE only uses the lower 32 bits, since
+it can be called from either 32 or 64-bit applications.
diff --git a/cfe/cfe/applets/cfe_applet.lds b/cfe/cfe/applets/cfe_applet.lds
new file mode 100644
index 0000000..e1b33e9
--- /dev/null
+++ b/cfe/cfe/applets/cfe_applet.lds
@@ -0,0 +1,37 @@
+OUTPUT_ARCH(mips)
+ENTRY(__start)
+SECTIONS
+{
+ . = 0x20000000;
+/* . = 0x81000000; */
+ .text :
+ {
+ _ftext = . ;
+ *(.init)
+ eprol = .;
+ *(.text)
+ *(.fini)
+ *(.rodata)
+ _etext = .;
+ }
+
+ .data :
+ {
+ _gp = ALIGN(16) + 0x8000;
+ _fdata = . ;
+ *(.data)
+ CONSTRUCTORS
+ *(.sdata)
+ }
+ _edata = .;
+ _fbss = .;
+ .sbss : {
+ *(.sbss)
+ *(.scommon)
+ }
+ .bss : {
+ *(.bss)
+ *(COMMON)
+ }
+ _end = .;
+}
diff --git a/cfe/cfe/applets/download.c b/cfe/cfe/applets/download.c
new file mode 100644
index 0000000..911c649
--- /dev/null
+++ b/cfe/cfe/applets/download.c
@@ -0,0 +1,163 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Null device mode driver File: download.c
+ *
+ * Small program (placeholder) to download to a 1250 in PCI Device Mode
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "cfe_api.h"
+
+int conhandle;
+
+
+void appletmain(long handle,long vector,
+ long reserved,long seal);
+
+
+
+
+/* *********************************************************************
+ * console_write(buffer,length)
+ *
+ * Write text to the console. If the console is not open and
+ * we're "saving" text, put the text on the in-memory queue
+ *
+ * Input parameters:
+ * buffer - pointer to data
+ * length - number of characters to write
+ *
+ * Return value:
+ * number of characters written or <0 if error
+ ********************************************************************* */
+
+static int console_write(unsigned char *buffer,int length)
+{
+ int res;
+
+ /*
+ * Do nothing if no console
+ */
+
+ if (conhandle == -1) return -1;
+
+ /*
+ * Write text to device
+ */
+
+ for (;;) {
+ res = cfe_write(conhandle,buffer,length);
+ if (res < 0) break;
+ buffer += res;
+ length -= res;
+ if (length == 0) break;
+ }
+
+ if (res < 0) return -1;
+ return 0;
+}
+
+
+/* *********************************************************************
+ * console_xprint(str)
+ *
+ * printf callback for the console device. the "xprintf"
+ * routine ends up calling this. This routine also cooks the
+ * output, turning "\n" into "\r\n"
+ *
+ * Input parameters:
+ * str - string to write
+ *
+ * Return value:
+ * number of characters written
+ ********************************************************************* */
+
+static int console_xprint(const char *str)
+{
+ int count = 0;
+ int len;
+ const char *p;
+
+ /* Convert CR to CRLF as we write things out */
+
+ while ((p = strchr(str,'\n'))) {
+ console_write((char *) str,p-str);
+ console_write("\r\n",2);
+ count += (p-str);
+ str = p + 1;
+ }
+
+ len = strlen(str);
+ console_write((char *) str, len);
+ count += len;
+
+ return count;
+}
+
+
+void appletmain(long handle,long vector,
+ long ept,long seal)
+{
+ void (*reboot)(void) = (void *) (uintptr_t) (int) 0xBFC00000;
+ char str[100];
+
+ xprinthook = console_xprint;
+
+ cfe_init(handle,ept);
+
+ conhandle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
+
+ str[0] = 0;
+ cfe_getenv("BOOT_CONSOLE",str,sizeof(str));
+
+ xprintf("\nHello, world. Console = %s\n",str);
+
+ xprintf("\nThis is a null device driver that just restarts CFE\n");
+ xprintf("Rebuild the host's CFE to replace it with your driver.\n\n");
+
+ xprintf("Exiting to CFE\n\n");
+
+ cfe_exit(CFE_FLG_WARMSTART,0);
+
+ (*reboot)();
+}
diff --git a/cfe/cfe/applets/download.lds b/cfe/cfe/applets/download.lds
new file mode 100644
index 0000000..7f6e6be
--- /dev/null
+++ b/cfe/cfe/applets/download.lds
@@ -0,0 +1,12 @@
+OUTPUT_FORMAT("elf32-bigmips")
+OUTPUT_ARCH("mipssb1")
+
+SECTIONS
+{
+ .rodata :
+ {
+ download_start = .;
+ *(.data);
+ download_end = .;
+ }
+}
diff --git a/cfe/cfe/applets/minicrt0.S b/cfe/cfe/applets/minicrt0.S
new file mode 100644
index 0000000..937f240
--- /dev/null
+++ b/cfe/cfe/applets/minicrt0.S
@@ -0,0 +1,95 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Mini startup module for CFE apps File: minicrt0.S
+ *
+ * About the most minimal startup routine you can get.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "sbmips.h"
+
+/*
+ * This module should be linked first!
+ */
+
+#define STACK_SIZE 8192
+
+ .bss
+ .comm stack_bottom,STACK_SIZE
+ .comm __junk,4
+
+ .text
+
+ .extern appletmain
+ .globl __start
+
+__start:
+
+ /*
+ * Set up our GP (in case we're using it)
+ * Set up the stack pointer (don't use CFE's stack)
+ */
+
+ la gp,_gp
+ la sp,stack_bottom+STACK_SIZE-32
+
+ /*
+ * Zero BSS. No need to do this very efficiently, do it
+ * 32 bits at a time to ensure we can compile this
+ * with -mips1.
+ */
+
+ la t0,_fbss
+ la t1,_end
+
+1: sw zero,0(t0)
+ add t0,4
+ blt t0,t1,1b
+
+ /*
+ * Jump to main program. Note that we didn't trash A0..A3,
+ * our application will need them. So, if you add stuff here,
+ * be sure to preserve the A0..A3 registers for the C code.
+ */
+
+ j appletmain
+
diff --git a/cfe/cfe/applets/test.c b/cfe/cfe/applets/test.c
new file mode 100644
index 0000000..9122456
--- /dev/null
+++ b/cfe/cfe/applets/test.c
@@ -0,0 +1,211 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * API test program File: test.c
+ *
+ * Small program to test CFE's external API
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "cfe_api.h"
+
+int conhandle;
+
+
+void appletmain(unsigned long handle,unsigned long vector,
+ unsigned long reserved,unsigned long seal);
+
+
+
+
+/* *********************************************************************
+ * console_write(buffer,length)
+ *
+ * Write text to the console. If the console is not open and
+ * we're "saving" text, put the text on the in-memory queue
+ *
+ * Input parameters:
+ * buffer - pointer to data
+ * length - number of characters to write
+ *
+ * Return value:
+ * number of characters written or <0 if error
+ ********************************************************************* */
+
+static int console_write(unsigned char *buffer,int length)
+{
+ int res;
+
+ /*
+ * Do nothing if no console
+ */
+
+ if (conhandle == -1) return -1;
+
+ /*
+ * Write text to device
+ */
+
+ for (;;) {
+ res = cfe_write(conhandle,buffer,length);
+ if (res < 0) break;
+ buffer += res;
+ length -= res;
+ if (length == 0) break;
+ }
+
+ if (res < 0) return -1;
+ return 0;
+}
+
+
+/* *********************************************************************
+ * console_xprint(str)
+ *
+ * printf callback for the console device. the "xprintf"
+ * routine ends up calling this. This routine also cooks the
+ * output, turning "\n" into "\r\n"
+ *
+ * Input parameters:
+ * str - string to write
+ *
+ * Return value:
+ * number of characters written
+ ********************************************************************* */
+
+static int console_xprint(const char *str)
+{
+ int count = 0;
+ int len;
+ const char *p;
+
+ /* Convert CR to CRLF as we write things out */
+
+ while ((p = strchr(str,'\n'))) {
+ console_write((char *) str,p-str);
+ console_write("\r\n",2);
+ count += (p-str);
+ str = p + 1;
+ }
+
+ len = strlen(str);
+ console_write((char *) str, len);
+ count += len;
+
+ return count;
+}
+
+
+#if 0
+static int myxprinthook(const char *str)
+{
+ int count = 0;
+ int len;
+ const char *p;
+
+ /* Convert CR to CRLF as we write things out */
+
+ while ((p = strchr(str,'\r'))) {
+ cfe_write(conhandle,(char *) str,p-str+1);
+ cfe_write(conhandle,"\n",1);
+ count += (p-str);
+ str = p + 1;
+ }
+
+ len = strlen(str);
+ cfe_write(conhandle,(char *) str, len);
+ count += len;
+
+ return count;
+}
+#endif
+
+void appletmain(unsigned long handle,unsigned long vector,
+ unsigned long ept,unsigned long seal)
+{
+ void (*reboot)(void) = (void *) (uintptr_t) (int) 0xBFC00000;
+ char str[100];
+ cfe_fwinfo_t info;
+ int idx;
+ int res;
+ uint64_t start,length,type;
+
+ xprinthook = console_xprint;
+
+ cfe_init(handle,ept);
+
+ conhandle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
+
+ str[0] = 0;
+ cfe_getenv("BOOT_CONSOLE",str,sizeof(str));
+
+ xprintf("Hello, world. Console = %s\n",str);
+ xprintf("API Seal = %08X\n",(int)seal);
+ xprintf("Entrypoint=%08X Handle=%08X\n",(int)ept,(int)handle);
+ idx = 0;
+
+ cfe_getfwinfo(&info);
+ xprintf("CFE version: %08llX\n",info.fwi_version);
+ xprintf("Flags: %08llX\n",info.fwi_flags);
+ xprintf("Total memory: %08llX\n",info.fwi_totalmem);
+ xprintf("Board ID: %08llX\n",info.fwi_boardid);
+ xprintf("Bootarea VA: %08llX\n",info.fwi_bootarea_va);
+ xprintf("Bootarea PA: %08llX\n",info.fwi_bootarea_pa);
+ xprintf("Bootarea Size: %08llX\n",info.fwi_bootarea_size);
+
+ xprintf("Memory map:\n");
+ for (;;) {
+ if ((res = cfe_enummem(idx,1,&start,&length,&type) != 0)) break;
+ xprintf("Memory at %016llX length %016llX type %ld\n",
+ start,length,type);
+ idx++;
+ }
+
+ xprintf("Exiting to CFE\n\n");
+
+ cfe_exit(CFE_FLG_WARMSTART,0);
+
+ (*reboot)();
+
+}
diff --git a/cfe/cfe/applets/vapitest.S b/cfe/cfe/applets/vapitest.S
new file mode 100644
index 0000000..a57a563
--- /dev/null
+++ b/cfe/cfe/applets/vapitest.S
@@ -0,0 +1,96 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Verification Test APIs File: vapitest.S
+ *
+ * This module contains special low-level routines for use
+ * by verification programs.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "sbmips.h"
+
+
+#include "vapi.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+ .text
+
+LEAF(_start)
+
+ VAPI_LOG_SETBUF(0x80030000,0x80040000)
+
+
+ VAPI_LOG_CONST(0x100,0xABCDEF)
+ VAPI_LOG_REG(0x101,sp)
+ VAPI_LOG_BUFFER(0x102,testbuf,10)
+ VAPI_PUTS("Hello world.\n")
+ VAPI_LOG_SOCSTATE(0x103,SOC_AGENT_DUART)
+ VAPI_PRINTGPRS();
+ VAPI_LOG_CONST(0x1EE,0xEEEEEEEE)
+ VAPI_LOG_GPRS(0x199)
+ VAPI_SETLEDS('V','A','P','I')
+
+ VAPI_EXIT_CONST(0)
+
+
+END(_start)
+
+testbuf: .dword 0x123456789ABCDEF0
+ .dword 0xAABBCCDD
+ .dword 0xAABBCCDD
+ .dword 0xAABBCCDD
+ .dword 0xAABBCCDD
+ .dword 0xAABBCCDD
+ .dword 0xAABBCCDD
+ .dword 0xAABBCCDD
+ .dword 0xAABBCCDD
+ .dword 0xFEDCBA9876543210
+
+
+
+/* *********************************************************************
+ * End
+ ********************************************************************* */
+
+
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm63xx_util.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm63xx_util.h
new file mode 100755
index 0000000..273b9c7
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm63xx_util.h
@@ -0,0 +1,167 @@
+/***************************************************************************
+ * Broadcom Corp. Confidential
+ * Copyright 2001, 2002 Broadcom Corp. All Rights Reserved.
+ *
+ * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED
+ * SOFTWARE LICENSE AGREEMENT BETWEEN THE USER AND BROADCOM.
+ * YOU HAVE NO RIGHT TO USE OR EXPLOIT THIS MATERIAL EXCEPT
+ * SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
+ *
+ ***************************************************************************
+ * File Name : bcm63xx_util.h
+ *
+ * Created on : 04/18/2002 seanl
+ ***************************************************************************/
+
+#if !defined(_BCM63XX_UTIL_H_)
+#define _BCM63XX_UTIL_H_
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_devfuncs.h"
+#include "cfe_timer.h"
+#include "cfe_ioctl.h"
+#include "cfe_error.h"
+#include "env_subr.h"
+#include "ui_command.h"
+#include "cfe.h"
+#include "net_ebuf.h"
+#include "net_ether.h"
+#include "net_api.h"
+#include "cfe_fileops.h"
+#include "bsp_config.h"
+#include "cfe_mem.h"
+#include "cfe_loader.h"
+#include "addrspace.h"
+
+#include "dev_bcm63xx_flash.h"
+#include "bcm_hwdefs.h"
+#include "bcmTag.h"
+#include "boardparms.h"
+#include "boardparms_voice.h"
+#include "bcm_map.h"
+
+extern unsigned long cfe_sdramsize;
+
+#define NAND_FLASH_BOOT_IMAGE_NAME "vmlinux.lz"
+
+#define BOARD_IMAGE_DOWNLOAD_ADDRESS \
+ ((cfe_sdramsize > 0x00800000) ? 0x80800000 : 0x80000000)
+#define BOARD_IMAGE_DOWNLOAD_SIZE \
+ ((cfe_sdramsize > 0x00800000) ? cfe_sdramsize - 0x00800000 : 0x00400000)
+
+#define MAX_PROMPT_LEN 50 // assume no one wants to type more than 50 chars
+#define MAX_MAC_STR_LEN 19 // mac address string 18+1 in regular format
+#define PROMPT_DEFINE_LEN 2
+#define MASK_LEN 8 // vxworks like ffffff00
+
+typedef struct
+{
+ char* promptName;
+ char* errorPrompt;
+ char promptDefine[PROMPT_DEFINE_LEN];
+ char parameter[MAX_PROMPT_LEN];
+ int maxValueLength;
+ int (*func)(char *);
+ int enabled;
+} PARAMETER_SETTING, *PPARAMETER_SETTING;
+
+#define IP_PROMPT "Invalid ip address. eg. 192.168.1.200[:ffffff00]"
+#define RUN_FROM_PROMPT "f = jump to flash; h = tftpd from host"
+#define HOST_FN_PROMPT "eg. vmlinux"
+#define FLASH_FN_PROMPT "eg. bcm963xx_fs_kernel"
+#define BOOT_DELAY_PROMPT "range 0-9, 0=forever prompt"
+#define BOOT_PARTITION_PROMPT "1 = latest image, 2 = previous image"
+#define AFE_PROMPT "Invalid AFE ID eg. 0x10608100"
+
+// error input prompts
+#define BOARDID_STR_PROMPT "Invalid board ID"
+#define MAC_CT_PROMPT "Invalid MAC addresses number: 1 - 32"
+#define MAC_ADDR_PROMPT "Invalid MAC address format: eg. 12:34:56:ab:cd:ef or 123456abcdef"
+#define PSI_SIZE_PROMPT "Invalid PSI size: (1-64) Kbytes"
+#define BACKUP_PSI_PROMPT "Enable Backup PSI (0 or 1)"
+#define SYSLOG_SIZE_PROMPT "Invalid System Log size: (0-256) Kbytes"
+#define CPU_TP_PROMPT "Invalid thread number: [0|1]"
+#define GPON_SN_PROMPT "Invalid GPON Serial Number"
+#define GPON_PW_PROMPT "Invalid GPON Password"
+#define WPS_DEVICE_PIN_PROMPT "Invalid WPS Device Pin"
+
+// bootline definition:
+// Space is the deliminator of the parameters. Currently supports following parameters:
+// t=xxx.xxx.xxx.xxx h=xxx.xxx.xxx.xxx g=xxx.xxx.xxx.xxx r=f/h (run from flash or host)
+// f=vmlinux (if r=h) i=bcm963xx_fs_kernel d=3 (default delay, range 0-9, 0=forever prompt)
+
+#define BOOT_IP_LEN 18 // "t=xxx.xxx.xxx.xxx"
+#define BOOT_FILENAME_LEN 50 // "f=vmlinux"
+
+typedef struct
+{
+ char boardIp[BOOT_IP_LEN];
+ char boardMask[BOOT_IP_LEN]; // set for the board only and ignore for the host/gw. fmt :ffffff00
+ char hostIp[BOOT_IP_LEN];
+ char gatewayIp[BOOT_IP_LEN];
+ char runFrom;
+ char hostFileName[BOOT_FILENAME_LEN];
+ char flashFileName[BOOT_FILENAME_LEN];
+ int bootDelay;
+ char bootPartition;
+} BOOT_INFO, *PBOOT_INFO;
+
+#define LED_OFF 0
+#define LED_ON 1
+
+extern void getBootLine(void);
+extern void setDefaultBootline(void);
+extern int printSysInfo(void);
+extern int changeBootLine(void);
+extern int changeAfeId(void);
+extern void dumpHex(unsigned char *start, int len);
+extern BOOT_INFO bootInfo;
+extern void enet_init(void);
+extern int verifyTag(PFILE_TAG pTag, int verbose);
+extern int flashImage(unsigned char *ptr);
+extern int writeWholeImage(unsigned char *ptr, int size);
+
+/* Foxconn add start by Cliff Wang, 03/23/2010 */
+extern int bcm63xx_run(int breakIntoCfe);
+/* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+extern int getPartitionFromTag( PFILE_TAG pTag );
+extern PFILE_TAG getTagFromPartition(int imageNumber);
+extern PFILE_TAG getBootImageTag(void);
+extern int parsexdigit(char str);
+extern int setDefaultBoardParam(void); /* Bob added to set default board parameters, 11/01/2010 */
+extern int setBoardParam(void);
+extern int setGponBoardParam(void);
+extern int setWpsDevicePinBoardParam(void);
+extern int setVoiceBoardParam(void);
+extern int getBoardParam(void);
+extern void displayBoardParam(void);
+extern int processPrompt(PPARAMETER_SETTING promptPtr, int promptCt);
+extern UINT32 getCrc32(unsigned char *pdata, UINT32 size, UINT32 crc);
+extern int yesno(void);
+extern int bcm63xx_cfe_rawload(cfe_loadargs_t *la);
+extern int bcm63xx_cfe_elfload(cfe_loadargs_t *la);
+extern void setGpio (unsigned short led_gpio, unsigned short led_state);
+extern void setLed ( unsigned short led, unsigned short led_state );
+extern void setAllLedsOff(void);
+extern void setPowerOnLedOn(void);
+extern void setBreakIntoCfeLed(void);
+extern void softReset(void);
+extern void validateNandPartTbl(PNVRAM_DATA pNvramData);
+extern void writeNvramData(PNVRAM_DATA pNvramData);
+extern int readNvramData(PNVRAM_DATA pNvramData);
+
+/* Foxconn add start by Jenny Zhao, 07/02/2008*/
+extern int nmrp_led_toggle(void);
+extern int power_led_toggle(int state);
+extern int verify_board_id(char *buf);
+/* Foxconn add end by Jenny Zhao, 07/02/2008*/
+#endif // _BCM63XX_UTIL_H_
+
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_common.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_common.h
new file mode 100755
index 0000000..136267a
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_common.h
@@ -0,0 +1,32 @@
+/*
+<:copyright-broadcom
+
+ Copyright (c) 2004 Broadcom Corporation
+ All Rights Reserved
+ No portions of this material may be reproduced in any form without the
+ written permission of:
+ Broadcom Corporation
+ 16215 Alton Parkway
+ Irvine, California 92619
+ All information contained in this document is Broadcom Corporation
+ company private, proprietary, and trade secret.
+
+:>
+*/
+#ifndef __BCM_COMMON_H
+#define __BCM_COMMON_H
+
+#if defined (_BCM96328_)
+#include "6328_common.h"
+#endif
+#if defined (_BCM96362_)
+#include "6362_common.h"
+#endif
+#if defined (_BCM96368_)
+#include "6368_common.h"
+#endif
+#if defined (_BCM96816_)
+#include "6816_common.h"
+#endif
+
+#endif
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_cpu.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_cpu.h
new file mode 100755
index 0000000..e033936
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_cpu.h
@@ -0,0 +1,32 @@
+/*
+<:copyright-broadcom
+
+ Copyright (c) 2004 Broadcom Corporation
+ All Rights Reserved
+ No portions of this material may be reproduced in any form without the
+ written permission of:
+ Broadcom Corporation
+ 16215 Alton Parkway
+ Irvine, California 92619
+ All information contained in this document is Broadcom Corporation
+ company private, proprietary, and trade secret.
+
+:>
+*/
+#ifndef __BCM_CPU_H
+#define __BCM_CPU_H
+
+#if defined (_BCM96328_)
+#include "6328_cpu.h"
+#endif
+#if defined (_BCM96362_)
+#include "6362_cpu.h"
+#endif
+#if defined (_BCM96368_)
+#include "6368_cpu.h"
+#endif
+#if defined (_BCM96816_)
+#include "6816_cpu.h"
+#endif
+
+#endif
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_map.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_map.h
new file mode 100755
index 0000000..0383431
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcm_map.h
@@ -0,0 +1,32 @@
+/*
+<:copyright-broadcom
+
+ Copyright (c) 2004 Broadcom Corporation
+ All Rights Reserved
+ No portions of this material may be reproduced in any form without the
+ written permission of:
+ Broadcom Corporation
+ 16215 Alton Parkway
+ Irvine, California 92619
+ All information contained in this document is Broadcom Corporation
+ company private, proprietary, and trade secret.
+
+:>
+*/
+#ifndef __BCM_MAP_H
+#define __BCM_MAP_H
+
+#if defined (_BCM96328_)
+#include "6328_map.h"
+#endif
+#if defined (_BCM96362_)
+#include "6362_map.h"
+#endif
+#if defined (_BCM96368_)
+#include "6368_map.h"
+#endif
+#if defined (_BCM96816_)
+#include "6816_map.h"
+#endif
+
+#endif
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcmmii.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcmmii.h
new file mode 100755
index 0000000..a33de5c
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcmmii.h
@@ -0,0 +1,164 @@
+/*
+<:copyright-broadcom
+
+ Copyright (c) 2004 Broadcom Corporation
+ All Rights Reserved
+ No portions of this material may be reproduced in any form without the
+ written permission of:
+ Broadcom Corporation
+ 16215 Alton Parkway
+ Irvine, California 92619
+ All information contained in this document is Broadcom Corporation
+ company private, proprietary, and trade secret.
+
+:>
+*/
+#ifndef _BCMMII_H_
+#define _BCMMII_H_
+
+#include "dev_bcm63xx_eth.h"
+
+/*---------------------------------------------------------------------*/
+/* Broadcom PHY MII register address */
+/* use when PhyType is BP_ENET_INTERNAL_PHY */
+/*---------------------------------------------------------------------*/
+#define BCM_PHY_ID_M 0x1F
+#define IsExtPhyId(id) ((id & BCM_PHY_ID_M) >= 0x10)
+//#define BCM_WAN_PORT 0x40
+//#define IsWanPort(id) (((id) & BCM_WAN_PORT) && ((id) != 0xFF))
+
+#define MII_ASR 0x19
+#define MII_INTERRUPT 0x1A
+#define MII_RESERVED_1B 0x1B
+#define MII_BRCM_TEST 0x1F
+
+/* MII ASR register. */
+#define MII_ASR_DONE(r) ((r & 0x8000) != 0)
+#define MII_ASR_LINK(r) ((r & 0x0004) != 0)
+#define MII_ASR_FDX(r) (((r & 0x0700) == 0x0700) || ((r & 0x0700) == 0x0500) || ((r & 0x0700) == 0x0200))
+#define MII_ASR_1000(r) (((r & 0x0700) == 0x0700) || ((r & 0x0700) == 0x0600))
+#define MII_ASR_100(r) (((r & 0x0700) == 0x0500) || ((r & 0x0700) == 0x0300))
+#define MII_ASR_10(r) (((r & 0x0700) == 0x0200) || ((r & 0x0700) == 0x0100))
+
+/* Reserved 0x1B register */
+#define MII_RESERVED_1B_ACT_LED 0x0004
+
+/* Broadcom Test register. */
+#define MII_BRCM_TEST_SHADOW2_ENABLE 0x0004
+
+/* MII Interrupt register. */
+#define MII_INTR_ENABLE 0x4000
+
+#define BCM54610_PHYID2 0xBD63
+#define BCM_PHYID_M 0xFFF0
+
+#define MII_REGISTER_1C 0x1c
+ #define MII_1C_WRITE_ENABLE (1 << 15)
+ #define MII_1C_SHADOW_REG_SEL_S 10
+ #define MII_1C_SHADOW_REG_SEL_M 0x1F
+#define MII_1C_SHADOW_CLK_ALIGN_CTRL 0x3
+ #define GTXCLK_DELAY_BYPASS_DISABLE (1 << 9)
+#define MII_1C_SHADOW_LED_CONTROL 0x9
+ #define ACT_LINK_LED_ENABLE (1 << 4)
+#define MII_1C_EXTERNAL_CONTROL_1 0xB
+ #define LOM_LED_MODE (1 << 2)
+
+#define PAGE_CONTROL 0x00
+#define PAGE_SELECT 0xff
+#define PAGE_MANAGEMENT 0x02
+
+/* Control page registers */
+#define REG_MII_PORT_CONTROL 0x08
+#define REG_SWITCH_MODE 0x0b
+#define REG_CONTROL_MII1_PORT_STATE_OVERRIDE 0x0e
+#define REG_POWER_DOWN_MODE 0x0f
+
+/* MII Port Control Register, Page 0x00 Address 0x08 */
+#define REG_MII_PORT_CONTROL_RX_UCST_EN 0x10
+#define REG_MII_PORT_CONTROL_RX_MCST_EN 0x08
+#define REG_MII_PORT_CONTROL_RX_BCST_EN 0x04
+
+/* Switch mode register, Page 0x00 Address 0x0b */
+#define REG_SWITCH_MODE_FRAME_MANAGE_MODE 0x01
+#define REG_SWITCH_MODE_SW_FWDG_EN 0x02
+
+/* MII1 Port State Override Register Page 0x00 Address 0x0e */
+#define REG_CONTROL_MPSO_MII_SW_OVERRIDE 0x80
+#define REG_CONTROL_MPSO_REVERSE_MII 0x10
+#define REG_CONTROL_MPSO_LP_FLOW_CONTROL 0x08
+#define REG_CONTROL_MPSO_SPEED100 0x04
+#define REG_CONTROL_MPSO_SPEED1000 0x08
+#define REG_CONTROL_MPSO_FDX 0x02
+#define REG_CONTROL_MPSO_LINKPASS 0x01
+
+/* Power down mode register Page 0x00 Address 0x0f */
+#define REG_POWER_DOWN_MODE_PORT1_PHY_DISABLE 0x01
+#define REG_POWER_DOWN_MODE_PORT2_PHY_DISABLE 0x02
+#define REG_POWER_DOWN_MODE_PORT3_PHY_DISABLE 0x04
+#define REG_POWER_DOWN_MODE_PORT4_PHY_DISABLE 0x08
+#define REG_POWER_DOWN_MODE_PORT5_PHY_DISABLE 0x10
+
+/* Switch control register page 0x0 */
+#define REG_SWITCH_CONTROL 0x20
+#define REG_SWITCH_CONTROL_MII_DUMP_FWD_EN 0x1
+
+/* Device ID register page 0x02 */
+#define REG_DEVICE_ID 0x30
+#define REG_GLOBAL_CONFIG 0x00
+#define REG_BRCM_HDR_CTRL 0x03
+
+/* Global Configuration Regiater Page 0x02 Address 0x00 */
+#define ENABLE_MII_PORT 0x80
+
+/* Broadcom Header Control Register Page 0x02 Address 0x03*/
+#define REG_BRCM_HDR_ENABLE 0x01
+
+
+
+/*---------------------------------------------------------------------*/
+/* 5325 Switch SPI Interface */
+/* use when configuration type is BP_ENET_CONFIG_SPI_SSB_x */
+/*---------------------------------------------------------------------*/
+#define BCM5325_SPI_CMD_LEN 1
+#define BCM5325_SPI_ADDR_LEN 1
+#define BCM5325_SPI_PREPENDCNT (BCM5325_SPI_CMD_LEN+BCM5325_SPI_ADDR_LEN)
+
+/* 5325 SPI Status Register */
+#define BCM5325_SPI_STS 0xfe
+
+/* 5325 SPI Status Register definition */
+#define BCM5325_SPI_CMD_RACK 0x20
+
+/* 5325 Command Byte definition */
+#define BCM5325_SPI_CMD_READ 0x00 /* bit 0 - Read/Write */
+#define BCM5325_SPI_CMD_WRITE 0x01 /* bit 0 - Read/Write */
+#define BCM5325_SPI_CHIPID_MASK 0x7 /* bit 3:1 - Chip ID */
+#define BCM5325_SPI_CHIPID_SHIFT 1
+#define BCM5325_SPI_CMD_NORMAL 0x60 /* bit 7:4 - Mode */
+#define BCM5325_SPI_CMD_FAST 0x10 /* bit 4 - Mode */
+
+/*---------------------------------------------------------------------*/
+/* 5325 Switch Pseudo PHY MII Register */
+/* use when configuration type is BP_ENET_CONFIG_MDIO_PSEUDO_PHY */
+/*---------------------------------------------------------------------*/
+#define PSEUDO_PHY_ADDR 0x1e /* Pseduo PHY address */
+
+/* Pseudo PHY MII registers */
+#define REG_PSEUDO_PHY_MII_REG16 0x10 /* register 16 - Switch Register Set Access Control Register */
+#define REG_PSEUDO_PHY_MII_REG17 0x11 /* register 17 - Switch Register Set Read/Write Control Register */
+#define REG_PSEUDO_PHY_MII_REG24 0x18 /* register 24 - Switch Accesss Register bit 15:0 */
+#define REG_PSEUDO_PHY_MII_REG25 0x19 /* register 25 - Switch Accesss Register bit 31:16 */
+#define REG_PSEUDO_PHY_MII_REG26 0x20 /* register 26 - Switch Accesss Register bit 47:32 */
+#define REG_PSEUDO_PHY_MII_REG27 0x21 /* register 27 - Switch Accesss Register bit 63:48 */
+
+/*Pseudo PHY MII register 16 Switch Register Set Access Control Register */
+#define REG_PPM_REG16_SWITCH_PAGE_NUMBER_SHIFT 8 /* bit 8..15 - switch page number */
+#define REG_PPM_REG16_MDIO_ENABLE 0x01 /* bit 0 - set MDC/MDIO access enable */
+
+/*Pseudo PHY MII register 17 Switch Register Set Read/Write Control Register */
+#define REG_PPM_REG17_REG_NUMBER_SHIFT 8 /* bit 8..15 - switch register number */
+#define REG_PPM_REG17_OP_DONE 0x00 /* bit 0..1 - no operation */
+#define REG_PPM_REG17_OP_WRITE 0x01 /* bit 0..1 - write operation */
+#define REG_PPM_REG17_OP_READ 0x02 /* bit 0..1 - read operation */
+
+#endif /* _BCMMII_H_ */
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcmtypes.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcmtypes.h
new file mode 100755
index 0000000..9359663
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bcmtypes.h
@@ -0,0 +1,144 @@
+//
+// bcmtypes.h - misc useful typedefs
+//
+#ifndef BCMTYPES_H
+#define BCMTYPES_H
+
+// These are also defined in typedefs.h in the application area, so I need to
+// protect against re-definition.
+
+#ifndef _TYPEDEFS_H_
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned long uint32;
+typedef unsigned long long uint64;
+typedef signed char int8;
+typedef signed short int16;
+typedef signed long int32;
+typedef signed long long int64;
+#if !defined(__cplusplus)
+typedef int bool;
+#endif
+#endif
+
+typedef unsigned char byte;
+typedef unsigned long sem_t;
+
+typedef unsigned long HANDLE,*PULONG,DWORD,*PDWORD;
+typedef signed long LONG,*PLONG;
+
+typedef unsigned int *PUINT;
+typedef signed int INT;
+
+typedef unsigned short *PUSHORT;
+typedef signed short SHORT,*PSHORT,WORD,*PWORD;
+
+typedef unsigned char *PUCHAR;
+typedef signed char *PCHAR;
+
+typedef void *PVOID;
+
+typedef unsigned char BOOLEAN, *PBOOL, *PBOOLEAN;
+
+typedef unsigned char BYTE,*PBYTE;
+
+//#ifndef __GNUC__
+//The following has been defined in Vxworks internally: vxTypesOld.h
+//redefine under vxworks will cause error
+typedef signed int *PINT;
+
+typedef signed char INT8;
+typedef signed short INT16;
+typedef signed long INT32;
+
+typedef unsigned char UINT8;
+typedef unsigned short UINT16;
+typedef unsigned long UINT32;
+
+typedef unsigned char UCHAR;
+typedef unsigned short USHORT;
+typedef unsigned int UINT;
+typedef unsigned long ULONG;
+
+typedef void VOID;
+typedef unsigned char BOOL;
+
+//#endif /* __GNUC__ */
+
+
+// These are also defined in typedefs.h in the application area, so I need to
+// protect against re-definition.
+#ifndef TYPEDEFS_H
+
+#define MAX_INT16 32767
+#define MIN_INT16 -32768
+
+// Useful for true/false return values. This uses the
+// Taligent notation (k for constant).
+typedef enum
+{
+ kFalse = 0,
+ kTrue = 1
+} Bool;
+
+#endif
+
+/* macros to protect against unaligned accesses */
+
+#if 0
+/* first arg is an address, second is a value */
+#define PUT16( a, d ) { \
+ *((byte *)a) = (byte)((d)>>8); \
+ *(((byte *)a)+1) = (byte)(d); \
+}
+
+#define PUT32( a, d ) { \
+ *((byte *)a) = (byte)((d)>>24); \
+ *(((byte *)a)+1) = (byte)((d)>>16); \
+ *(((byte *)a)+2) = (byte)((d)>>8); \
+ *(((byte *)a)+3) = (byte)(d); \
+}
+
+/* first arg is an address, returns a value */
+#define GET16( a ) ( \
+ (*((byte *)a) << 8) | \
+ (*(((byte *)a)+1)) \
+)
+
+#define GET32( a ) ( \
+ (*((byte *)a) << 24) | \
+ (*(((byte *)a)+1) << 16) | \
+ (*(((byte *)a)+2) << 8) | \
+ (*(((byte *)a)+3)) \
+)
+#endif
+
+#ifndef YES
+#define YES 1
+#endif
+
+#ifndef NO
+#define NO 0
+#endif
+
+#ifndef IN
+#define IN
+#endif
+
+#ifndef OUT
+#define OUT
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define READ32(addr) (*(volatile UINT32 *)((ULONG)&addr))
+#define READ16(addr) (*(volatile UINT16 *)((ULONG)&addr))
+#define READ8(addr) (*(volatile UINT8 *)((ULONG)&addr))
+
+#endif
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bsp_config.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bsp_config.h
new file mode 100755
index 0000000..57e51bb
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/bsp_config.h
@@ -0,0 +1,94 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * BSP Configuration file File: bsp_config.h
+ *
+ * This module contains global parameters and conditional
+ * compilation settings for building CFE.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#define CFG_CMT 1
+
+#define CFG_INIT_L1 1 /* initialize the L1 cache */
+#define CFG_INIT_L2 0 /* there is no L2 cache */
+
+#define CFG_INIT_DRAM 1 /* initialize DRAM controller */
+#define CFG_DRAM_SIZE xxx /* size of DRAM if you don't initialize */
+ /* NOTE : Size is in kilobytes. */
+
+#define CFG_NETWORK 1 /* define to include network support */
+
+#define CFG_FATFS 0
+#define CFG_UI 1 /* Define to enable user interface */
+
+#define CFG_MULTI_CPUS 0 /* no multi-cpu support */
+
+#define CFG_HEAP_SIZE 1024 /* heap size in kilobytes */
+
+#define CFG_STACK_SIZE 8192 /* stack size (bytes, rounded up to K) */
+
+#define CFG_SERIAL_BAUD_RATE 115200 /* normal console speed */
+
+#define CFG_VENDOR_EXTENSIONS 0
+#define CFG_MINIMAL_SIZE 1
+
+/*
+ * These parameters control the flash driver's sector buffer.
+ * If you write environment variables or make small changes to
+ * flash sectors from user applications, you
+ * need to have the heap big enough to store a temporary sector
+ * for merging in small changes to flash sectors, so you
+ * should set CFG_FLASH_ALLOC_SECTOR_BUFFER in that case.
+ * Otherwise, you can provide an address in unallocated memory
+ * of where to place the sector buffer.
+ */
+
+#define CFG_FLASH_ALLOC_SECTOR_BUFFER 0 /* '1' to allocate sector buffer from the heap */
+#define CFG_FLASH_SECTOR_BUFFER_ADDR (1*1024*1024-128*1024) /* 1MB - 128K */
+#define CFG_FLASH_SECTOR_BUFFER_SIZE (128*1024)
+
+/*
+ * The flash staging buffer is where we store a flash image before we write
+ * it to the flash. It's too big for the heap.
+ */
+
+#define CFG_FLASH_STAGING_BUFFER_ADDR (1*1024*1024)
+#define CFG_FLASH_STAGING_BUFFER_SIZE (1*1024*1024)
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/dev_bcm63xx_eth.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/dev_bcm63xx_eth.h
new file mode 100755
index 0000000..7432231
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/dev_bcm63xx_eth.h
@@ -0,0 +1,127 @@
+/*
+<:copyright-broadcom
+
+ Copyright (c) 2002 Broadcom Corporation
+ All Rights Reserved
+ No portions of this material may be reproduced in any form without the
+ written permission of:
+ Broadcom Corporation
+ 16215 Alton Parkway
+ Irvine, California 92619
+ All information contained in this document is Broadcom Corporation
+ company private, proprietary, and trade secret.
+
+:>
+*/
+#ifndef __BCM63XX_ETH_H
+#define __BCM63XX_ETH_H
+
+#include "bcm_hwdefs.h"
+#include "bcm_map.h"
+#include "boardparms.h"
+
+// from linux if_ether.h
+#define ETH_ALEN 6 /* Octets in one ethernet addr */
+#define ETH_HLEN 14 /* Total octets in header. */
+#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
+#define ETH_DATA_LEN 1500 /* Max. octets in payload */
+#define ETH_CRC_LEN 4 /* CRC length */
+// end if_ether.h
+
+/*---------------------------------------------------------------------*/
+/* specify number of BDs and buffers to use */
+/*---------------------------------------------------------------------*/
+#define NR_TX_BDS 20
+#define NR_RX_BDS 20
+#define ENET_MAX_MTU_SIZE 1522 /* Body(1500) + EH_SIZE(14) + FCS(4) + VLAN(4) */
+#define DMA_MAX_BURST_LENGTH 8 /* in 64 bit words */
+#define ENET_BUF_SIZE ((ENET_MAX_MTU_SIZE + 63) & ~63)
+#define DMA_FC_THRESH_LO 5
+#define DMA_FC_THRESH_HI 10
+#define EMAC_TX_WATERMARK 32
+
+#define MAKE4(x) ((x[3] & 0xFF) | ((x[2] & 0xFF) << 8) | ((x[1] & 0xFF) << 16) | ((x[0] & 0xFF) << 24))
+#define MAKE2(x) ((x[1] & 0xFF) | ((x[0] & 0xFF) << 8))
+
+
+#define ERROR(x) xsprintf x
+#ifndef ASSERT
+#define ASSERT(x) if (x); else ERROR(("assert: "__FILE__" line %d\n", __LINE__));
+#endif
+
+//#define DUMP_TRACE
+
+#if defined(DUMP_TRACE)
+#define TRACE (x) xprintf x
+#else
+#define TRACE(x)
+#endif
+
+typedef struct PM_Addr {
+ uint16 valid; /* 1 indicates the corresponding address is valid */
+ unsigned char dAddr[ETH_ALEN];/* perfect match register's destination address */
+ unsigned int ref; /* reference count */
+} PM_Addr;
+#define MAX_PMADDR 4 /* # of perfect match address */
+
+#define NUM_PORTS 1
+
+typedef struct gpio_reg_addrs_t {
+ volatile uint16 *gpio_direction_reg;/* GPIO direction register */
+ volatile uint16 *gpio_value_reg; /* GPIO value register */
+} gpio_reg_addrs_t;
+
+typedef struct ethsw_info_t {
+ gpio_reg_addrs_t sbh;
+ uint32 ssl, clk, mosi, miso; /* GPIO mapping */
+ int cid, page; /* Current chip ID and page */
+} ethsw_info_t;
+
+typedef struct bcmenet_softc {
+
+ volatile DmaRegs *dmaCtrl;
+
+ /* transmit variables */
+ volatile DmaChannelCfg *txDma; /* location of transmit DMA register set */
+ volatile DmaDesc *txBds; /* Memory location of tx Dma BD ring */
+ volatile DmaDesc *txFirstBdPtr; /* ptr to first allocated Tx BD */
+ volatile DmaDesc *txNextBdPtr; /* ptr to next Tx BD to transmit with */
+ volatile DmaDesc *txLastBdPtr; /* ptr to last allocated Tx BD */
+
+ /* receive variables */
+ volatile DmaChannelCfg *rxDma; /* location of receive DMA register set */
+ volatile DmaDesc *rxBds; /* Memory location of rx bd ring */
+ volatile DmaDesc *rxFirstBdPtr; /* ptr to first allocated rx bd */
+ volatile DmaDesc *rxBdReadPtr; /* ptr to next rx bd to be processed */
+ volatile DmaDesc *rxLastBdPtr; /* ptr to last allocated rx bd */
+
+ uint32_t rxBuffers;
+ uint32_t txBuffers;
+
+ uint16 chipId; /* chip's id */
+ uint16 chipRev; /* step */
+ uint8_t hwaddr[ETH_ALEN];
+ ethsw_info_t ethSwitch; /* external switch */
+ ETHERNET_MAC_INFO EnetInfo;
+ uint32_t dmaPort;
+ uint32_t linkCheck;
+} bcmenet_softc;
+
+
+
+#define IncRxBdPtr(x, s) if (x == ((bcmenet_softc *)s)->rxLastBdPtr) \
+ x = ((bcmenet_softc *)s)->rxBds; \
+ else x++
+#define InctxBdPtr(x, s) if (x == ((bcmenet_softc *)s)->txLastBdPtr) \
+ x = ((bcmenet_softc *)s)->txBds; \
+ else x++
+
+// extern and function prototype
+
+extern int32_t _getticks(void);
+
+#ifdef DUMP_DATA
+static void hexdump( unsigned char * src, int srclen, int rowlen, int rows );
+#endif
+
+#endif // __BCM63XX_ETH_H
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/dev_bcm63xx_flash.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/dev_bcm63xx_flash.h
new file mode 100755
index 0000000..d8e7f1d
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/dev_bcm63xx_flash.h
@@ -0,0 +1,38 @@
+/***************************************************************************
+ * Broadcom Corp. Confidential
+ * Copyright 2001 Broadcom Corp. All Rights Reserved.
+ *
+ * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED
+ * SOFTWARE LICENSE AGREEMENT BETWEEN THE USER AND BROADCOM.
+ * YOU HAVE NO RIGHT TO USE OR EXPLOIT THIS MATERIAL EXCEPT
+ * SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
+ *
+ ***************************************************************************
+ * File Name : dev_bcm63xx_flash.h
+ *
+ * Created on : 04/18/2002 seanl
+ ***************************************************************************/
+
+#if !defined(_DEV_BCM63XX_FLASH_)
+#define _DEV_BCM63XX_FLASH_
+
+#include "bcmtypes.h"
+#include "bcm_hwdefs.h"
+
+// Used for images that do not contain a FILE_TAG record.
+#define FLASH_IMAGE_START_ADDR (FLASH_BASE + FLASH_LENGTH_BOOT_ROM)
+
+// FLASH_ADDR_INFO is now defined in flash_common.h
+#include "flash_common.h"
+
+extern void kerSysFlashInit(void);
+extern void kerSysFlashAddrInfoGet(PFLASH_ADDR_INFO pflash_addr_info);
+extern int kerSysNvRamSet(unsigned char *string,int strLen,int offset);
+extern int kerSysNvRamGet(unsigned char *string,int strLen,int offset);
+extern int kerSysBcmImageSet( int flash_start_addr, unsigned char *string, int size, int fWholeImage);
+extern int kerSysErasePsi(void);
+extern int kerSysEraseNvRam(void);
+extern unsigned long kerSysReadFromFlash(void *toaddr, unsigned long fromaddr, unsigned long len);
+
+#endif /* _DEV_BCM63XX_FLASH_ */
+
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/include/jffs2.h b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/jffs2.h
new file mode 100755
index 0000000..586fb55
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/include/jffs2.h
@@ -0,0 +1,251 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2001-2003 Red Hat, Inc.
+ *
+ * Created by David Woodhouse <dwmw2@infradead.org>
+ *
+ * For licensing information, see the file 'LICENCE' in the
+ * jffs2 directory.
+ *
+ * $Id: jffs2.h,v 1.38 2005/09/26 11:37:23 havasi Exp $
+ *
+ */
+
+#ifndef __LINUX_JFFS2_H__
+#define __LINUX_JFFS2_H__
+
+//include <linux/magic.h>
+
+/* You must include something which defines the C99 uintXX_t types.
+ We don't do it from here because this file is used in too many
+ different environments. */
+
+/* Values we may expect to find in the 'magic' field */
+#define JFFS2_OLD_MAGIC_BITMASK 0x1984
+#define JFFS2_MAGIC_BITMASK 0x1985
+#define KSAMTIB_CIGAM_2SFFJ 0x8519 /* For detecting wrong-endian fs */
+#define JFFS2_EMPTY_BITMASK 0xffff
+#define JFFS2_DIRTY_BITMASK 0x0000
+
+#if defined(CONFIG_MTD_BRCMNAND)
+/* JFFS2 eraseblock header compat/incompat/rocompat features set */
+#define JFFS2_EBH_COMPAT_FSET 0x00
+#define JFFS2_EBH_INCOMPAT_FSET 0x00
+#define JFFS2_EBH_ROCOMPAT_FSET 0x00
+#endif
+
+/* Summary node MAGIC marker */
+#define JFFS2_SUM_MAGIC 0x02851885
+
+/* We only allow a single char for length, and 0xFF is empty flash so
+ we don't want it confused with a real length. Hence max 254.
+*/
+#define JFFS2_MAX_NAME_LEN 254
+
+/* How small can we sensibly write nodes? */
+#define JFFS2_MIN_DATA_LEN 128
+
+#define JFFS2_COMPR_NONE 0x00
+#define JFFS2_COMPR_ZERO 0x01
+#define JFFS2_COMPR_RTIME 0x02
+#define JFFS2_COMPR_RUBINMIPS 0x03
+#define JFFS2_COMPR_COPY 0x04
+#define JFFS2_COMPR_DYNRUBIN 0x05
+#define JFFS2_COMPR_ZLIB 0x06
+/* Compatibility flags. */
+#define JFFS2_COMPAT_MASK 0xc000 /* What do to if an unknown nodetype is found */
+#define JFFS2_NODE_ACCURATE 0x2000
+/* INCOMPAT: Fail to mount the filesystem */
+#define JFFS2_FEATURE_INCOMPAT 0xc000
+/* ROCOMPAT: Mount read-only */
+#define JFFS2_FEATURE_ROCOMPAT 0x8000
+/* RWCOMPAT_COPY: Mount read/write, and copy the node when it's GC'd */
+#define JFFS2_FEATURE_RWCOMPAT_COPY 0x4000
+/* RWCOMPAT_DELETE: Mount read/write, and delete the node when it's GC'd */
+#define JFFS2_FEATURE_RWCOMPAT_DELETE 0x0000
+
+#define JFFS2_NODETYPE_DIRENT (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 1)
+#define JFFS2_NODETYPE_INODE (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 2)
+#define JFFS2_NODETYPE_CLEANMARKER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
+#define JFFS2_NODETYPE_PADDING (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 4)
+
+#define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6)
+
+#define JFFS2_NODETYPE_XATTR (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 8)
+#define JFFS2_NODETYPE_XREF (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 9)
+
+#if defined(CONFIG_MTD_BRCMNAND)
+#define JFFS2_NODETYPE_ERASEBLOCK_HEADER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 5)
+#endif
+
+/* XATTR Related */
+#define JFFS2_XPREFIX_USER 1 /* for "user." */
+#define JFFS2_XPREFIX_SECURITY 2 /* for "security." */
+#define JFFS2_XPREFIX_ACL_ACCESS 3 /* for "system.posix_acl_access" */
+#define JFFS2_XPREFIX_ACL_DEFAULT 4 /* for "system.posix_acl_default" */
+#define JFFS2_XPREFIX_TRUSTED 5 /* for "trusted.*" */
+
+#define JFFS2_ACL_VERSION 0x0001
+
+// Maybe later...
+//#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
+//#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4)
+
+
+#define JFFS2_INO_FLAG_PREREAD 1 /* Do read_inode() for this one at
+ mount time, don't wait for it to
+ happen later */
+#define JFFS2_INO_FLAG_USERCOMPR 2 /* User has requested a specific
+ compression type */
+
+
+/* These can go once we've made sure we've caught all uses without
+ byteswapping */
+
+typedef struct {
+ uint32_t v32;
+} __attribute__((packed)) jint32_t;
+
+typedef struct {
+ uint32_t m;
+} __attribute__((packed)) jmode_t;
+
+typedef struct {
+ uint16_t v16;
+} __attribute__((packed)) jint16_t;
+
+struct jffs2_unknown_node
+{
+ /* All start like this */
+ jint16_t magic;
+ jint16_t nodetype;
+ jint32_t totlen; /* So we can skip over nodes we don't grok */
+ jint32_t hdr_crc;
+};
+
+struct jffs2_raw_dirent
+{
+ jint16_t magic;
+ jint16_t nodetype; /* == JFFS2_NODETYPE_DIRENT */
+ jint32_t totlen;
+ jint32_t hdr_crc;
+ jint32_t pino;
+ jint32_t version;
+ jint32_t ino; /* == zero for unlink */
+ jint32_t mctime;
+ uint8_t nsize;
+ uint8_t type;
+ uint8_t unused[2];
+ jint32_t node_crc;
+ jint32_t name_crc;
+ uint8_t name[0];
+};
+
+/* The JFFS2 raw inode structure: Used for storage on physical media. */
+/* The uid, gid, atime, mtime and ctime members could be longer, but
+ are left like this for space efficiency. If and when people decide
+ they really need them extended, it's simple enough to add support for
+ a new type of raw node.
+*/
+struct jffs2_raw_inode
+{
+ jint16_t magic; /* A constant magic number. */
+ jint16_t nodetype; /* == JFFS2_NODETYPE_INODE */
+ jint32_t totlen; /* Total length of this node (inc data, etc.) */
+ jint32_t hdr_crc;
+ jint32_t ino; /* Inode number. */
+ jint32_t version; /* Version number. */
+ jmode_t mode; /* The file's type or mode. */
+ jint16_t uid; /* The file's owner. */
+ jint16_t gid; /* The file's group. */
+ jint32_t isize; /* Total resultant size of this inode (used for truncations) */
+ jint32_t atime; /* Last access time. */
+ jint32_t mtime; /* Last modification time. */
+ jint32_t ctime; /* Change time. */
+ jint32_t offset; /* Where to begin to write. */
+ jint32_t csize; /* (Compressed) data size */
+ jint32_t dsize; /* Size of the node's data. (after decompression) */
+ uint8_t compr; /* Compression algorithm used */
+ uint8_t usercompr; /* Compression algorithm requested by the user */
+ jint16_t flags; /* See JFFS2_INO_FLAG_* */
+ jint32_t data_crc; /* CRC for the (compressed) data. */
+ jint32_t node_crc; /* CRC for the raw inode (excluding data) */
+ uint8_t data[0];
+};
+
+struct jffs2_raw_xattr {
+ jint16_t magic;
+ jint16_t nodetype; /* = JFFS2_NODETYPE_XATTR */
+ jint32_t totlen;
+ jint32_t hdr_crc;
+ jint32_t xid; /* XATTR identifier number */
+ jint32_t version;
+ uint8_t xprefix;
+ uint8_t name_len;
+ jint16_t value_len;
+ jint32_t data_crc;
+ jint32_t node_crc;
+ uint8_t data[0];
+} __attribute__((packed));
+
+struct jffs2_raw_xref
+{
+ jint16_t magic;
+ jint16_t nodetype; /* = JFFS2_NODETYPE_XREF */
+ jint32_t totlen;
+ jint32_t hdr_crc;
+ jint32_t ino; /* inode number */
+ jint32_t xid; /* XATTR identifier number */
+ jint32_t xseqno; /* xref sequencial number */
+ jint32_t node_crc;
+} __attribute__((packed));
+
+struct jffs2_raw_summary
+{
+ jint16_t magic;
+ jint16_t nodetype; /* = JFFS2_NODETYPE_SUMMARY */
+ jint32_t totlen;
+ jint32_t hdr_crc;
+ jint32_t sum_num; /* number of sum entries*/
+ jint32_t cln_mkr; /* clean marker size, 0 = no cleanmarker */
+ jint32_t padded; /* sum of the size of padding nodes */
+ jint32_t sum_crc; /* summary information crc */
+ jint32_t node_crc; /* node crc */
+ jint32_t sum[0]; /* inode summary info */
+};
+
+#if defined(CONFIG_MTD_BRCMNAND)
+struct jffs2_raw_ebh
+{
+ jint16_t magic;
+ jint16_t nodetype; /* == JFFS2_NODETYPE_ERASEBLOCK_HEADER */
+ jint32_t totlen;
+ jint32_t hdr_crc;
+ jint32_t node_crc;
+ uint8_t reserved; /* reserved for future use and alignment */
+ uint8_t compat_fset;
+ uint8_t incompat_fset;
+ uint8_t rocompat_fset;
+ jint32_t erase_count; /* the erase count of this erase block */
+ jint32_t data[0];
+} __attribute__((packed));
+#endif
+
+union jffs2_node_union
+{
+ struct jffs2_raw_inode i;
+ struct jffs2_raw_dirent d;
+ struct jffs2_raw_xattr x;
+ struct jffs2_raw_xref r;
+ struct jffs2_raw_summary s;
+ struct jffs2_unknown_node u;
+};
+
+/* Data payload for device nodes. */
+union jffs2_device_node {
+ jint16_t old;
+ jint32_t new;
+};
+
+#endif /* __LINUX_JFFS2_H__ */
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/Makefile b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/Makefile
new file mode 100755
index 0000000..7320c9d
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/Makefile
@@ -0,0 +1,55 @@
+BSPOBJS += \
+ dev_bcm63xx_eth.o \
+ dev_bcm63xx_uart.o \
+ dev_bcm63xx_flash.o \
+ flash_api.o \
+ flash_common.o \
+ bcm63xx_ram_boot.o \
+ bcm63xx_devs.o \
+ bcm63xx_board.o \
+ bcm63xx_cmd.o \
+ bcm63xx_util.o \
+ bcm63xx_ldr_raw.o \
+ bcm63xx_ldr_elf.o \
+ bcm63xx_main.o \
+ bcm63xx_env_subr.o \
+ bcm63xx_net_icmp.o \
+ bcm63xx_httpd.o \
+ bcmSpiRes.o \
+ bcmLegSpi.o \
+ boardparms.o \
+ boardparms_voice.o
+
+ifneq ($(strip $(BRCM_CHIP)),6368)
+BSPOBJS += \
+ bcmHsSpi.o
+endif
+
+BSPOBJS += \
+ robosw_reg.o
+
+ifeq ($(strip ${INC_CFI_FLASH_DRIVER}),1)
+BSPOBJS += \
+ cfiflash.o
+endif
+
+ifeq ($(strip ${INC_SPI_FLASH_DRIVER}),1)
+BSPOBJS += \
+ spiflash.o
+endif
+
+ifeq ($(strip ${INC_SPI_PROG_NAND}),1)
+BSPOBJS += \
+ nandflash.o
+endif
+
+ifeq ($(strip ${INC_NAND_FLASH_DRIVER}),1)
+BSPOBJS += \
+ nandflash.o
+endif
+
+ifeq ($(strip ${CFG_WEB_SERVER}),1)
+BSPOBJS += \
+ ul.o \
+ ulinfo.o
+endif
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_board.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_board.c
new file mode 100755
index 0000000..5baa66c
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_board.c
@@ -0,0 +1,830 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * bcm63xx_board.c utility functions for bcm63xx board
+ *
+ * Created on : 09/25/2002 seanl
+ *
+ *********************************************************************
+
+<:copyright-broadcom
+
+ Copyright (c) 2002 Broadcom Corporation
+ All Rights Reserved
+ No portions of this material may be reproduced in any form without the
+ written permission of:
+ Broadcom Corporation
+ 16215 Alton Parkway
+ Irvine, California 92619
+ All information contained in this document is Broadcom Corporation
+ company private, proprietary, and trade secret.
+
+:>
+*/
+
+#include "bcm63xx_util.h"
+#include "foxconnCfg.h"
+
+#define MAX_BOARD_ID_NAMES 16
+#define MAX_VOICE_BOARD_ID_NAMES 20
+
+static char g_boardIdNames[BP_BOARD_ID_LEN * MAX_BOARD_ID_NAMES];
+static int g_numBoardIdNames = 0;
+
+static char g_voiceBoardIdNames[BP_BOARD_ID_LEN * MAX_VOICE_BOARD_ID_NAMES];
+static int g_numVoiceBoardIdNames = 0;
+
+static int parsehwaddr(char *, uint8_t *);
+static int parseBoardIdStr(char *);
+static int parseVoiceBoardIdStr(char *);
+static int parsePsiSize(char *);
+static int parseBackupPsi(char *tpStr);
+static int parseSyslogSize(char *tpStr);
+static int parseMainTp(char *);
+static int parseMacAddrCount(char *);
+static int parseMacAddr(char *);
+static int charIsHex(char ch);
+static int parseGponSN(char *snStr);
+static int parseGponPW(char *pwStr);
+static int macNumToStr(unsigned char *, char *);
+static void getGponBoardParam(void);
+static int gponParamsInitialized(NVRAM_DATA *pNvramData);
+
+static int parseWpsDevicePin(char *pinStr);
+static void getWpsDevicePinBoardParam(void);
+#define PARAM_IDX_BOARD_NAME 0
+#define PARAM_IDX_NUM_MAC_ADDR 1
+#define PARAM_IDX_BASE_MAC_ADDR 2
+#define PARAM_IDX_PSI_SIZE 3
+#define PARAM_IDX_ENABLE_BACKUP_PSI 4
+#define PARAM_IDX_SYSLOG_SIZE 5
+#define PARAM_IDX_MAIN_THREAD_NUM 6
+
+#define PARAM_IDX_GPON_SN 0
+#define PARAM_IDX_GPON_PW 1
+
+#define PARAM_IDX_WPS_DEVICE_PIN 0
+
+#define PARAM_IDX_VOICE_BOARD_NAME 0
+
+static PARAMETER_SETTING gBoardParam[] =
+{
+ // prompt name Error Prompt Define Param Validation function
+ {"Board Id (0-# :", BOARDID_STR_PROMPT, "", "", 2,
+ parseBoardIdStr, TRUE},
+ {"Number of MAC Addresses (1-32) :", MAC_CT_PROMPT, "", "", 2,
+ parseMacAddrCount, TRUE},
+ {"Base MAC Address :", MAC_ADDR_PROMPT, "", "", 17,
+ parseMacAddr, TRUE},
+ {"PSI Size (1-64) KBytes :", PSI_SIZE_PROMPT, "", "", 2,
+ parsePsiSize, TRUE},
+ {"Enable Backup PSI [0|1] :", BACKUP_PSI_PROMPT, "", "", 1,
+ parseBackupPsi, TRUE},
+ {"System Log Size (0-256) KBytes :", SYSLOG_SIZE_PROMPT, "", "", 3,
+ parseSyslogSize, TRUE},
+ {"Main Thread Number [0|1] :", CPU_TP_PROMPT, "", "", 1,
+ parseMainTp, TRUE},
+ {NULL}
+};
+
+static int gNumBoardParams = (sizeof(gBoardParam) / sizeof(PARAMETER_SETTING))-1;
+
+static PARAMETER_SETTING gGponBoardParam[] =
+{
+ // prompt name Error Prompt Define Param Validation function
+ {"GPON Serial Number :", GPON_SN_PROMPT, "", "", 12,
+ parseGponSN, TRUE},
+ {"GPON Password :", GPON_PW_PROMPT, "", "", 10,
+ parseGponPW, TRUE},
+ {NULL}
+};
+
+static int gNumGponBoardParams = (sizeof(gGponBoardParam) / sizeof(PARAMETER_SETTING))-1;
+static int gGponParamsInitialized = 0;
+
+
+static PARAMETER_SETTING gWpsDevicePinBoardParam[] =
+{
+ // prompt name Error Prompt Define Param Validation function
+ {"Device Pin :", WPS_DEVICE_PIN_PROMPT, "", "", 8,
+ parseWpsDevicePin, TRUE},
+ {NULL}
+};
+
+static int gNumWpsDevicePinBoardParams = (sizeof(gWpsDevicePinBoardParam) / sizeof(PARAMETER_SETTING))-1;
+static int gWpsDevicePinInitialized = 0;
+
+static PARAMETER_SETTING gVoiceBoardParam[] =
+{
+ // prompt name Error Prompt Define Param Validation function
+ {"Voice Board Configuration (0-# :", BOARDID_STR_PROMPT, "", "", 2,
+ parseVoiceBoardIdStr, FALSE},
+ {NULL}
+};
+
+static int gNumVoiceBoardParams = (sizeof(gVoiceBoardParam) / sizeof(PARAMETER_SETTING))-1;
+static int gVoiceParamsInitialized = 0;
+
+
+static int parsehwaddr(char *str,uint8_t *hwaddr)
+{
+ int digit1,digit2;
+ int idx = 6;
+
+ if (strlen(str) == (MAX_MAC_STR_LEN - 7)) { // no ':' mac input format ie. 021800100801
+ while (*str && (idx > 0)) {
+ digit1 = parsexdigit(*str);
+ if (digit1 < 0)
+ return -1;
+ str++;
+ if (!*str)
+ return -1;
+ digit2 = parsexdigit(*str);
+ if (digit2 < 0)
+ return -1;
+ *hwaddr++ = (digit1 << 4) | digit2;
+ idx--;
+ str++;
+ }
+ return 0;
+ }
+
+ if (strlen(str) != MAX_MAC_STR_LEN-2)
+ return -1;
+ if (*(str+2) != ':' || *(str+5) != ':' || *(str+8) != ':' || *(str+11) != ':' || *(str+14) != ':')
+ return -1;
+
+ while (*str && (idx > 0)) {
+ digit1 = parsexdigit(*str);
+ if (digit1 < 0)
+ return -1;
+ str++;
+ if (!*str)
+ return -1;
+
+ if (*str == ':') {
+ digit2 = digit1;
+ digit1 = 0;
+ }
+ else {
+ digit2 = parsexdigit(*str);
+ if (digit2 < 0)
+ return -1;
+ str++;
+ }
+
+ *hwaddr++ = (digit1 << 4) | digit2;
+ idx--;
+
+ if (*str == ':')
+ str++;
+ }
+ return 0;
+}
+
+
+static int parseMacAddr(char * macStr)
+{
+ unsigned char tmpBuf[MAX_PROMPT_LEN];
+
+ return (parsehwaddr(macStr, tmpBuf));
+}
+
+
+static int parseBoardIdStr(char *boardIdStr)
+{
+ int ret = 1;
+ int boardId;
+
+ if (strlen (boardIdStr) != 0) {
+ boardId = atoi(boardIdStr);
+ if (boardId >= 0 && boardId < g_numBoardIdNames)
+ ret = 0;
+ }
+
+ return ret;
+}
+
+
+static int parseVoiceBoardIdStr(char *boardIdStr)
+{
+ int ret = 1;
+ int boardId;
+
+ if (strlen (boardIdStr) != 0) {
+ boardId = atoi(boardIdStr);
+ if (boardId >= 0 && boardId < g_numVoiceBoardIdNames)
+ ret = 0;
+ }
+
+ return ret;
+}
+
+
+static int parseMacAddrCount(char *ctStr)
+{
+ int count = atoi(ctStr);
+
+ if (count >= 1 && count <= NVRAM_MAC_COUNT_MAX)
+ return 0;
+ else
+ return 1;
+}
+
+static int parsePsiSize(char *tpStr)
+{
+ int psiSize = atoi(tpStr);
+
+ if (psiSize >= 1 && psiSize <= NVRAM_MAX_PSI_SIZE)
+ return 0;
+ else
+ return 1;
+}
+
+static int parseBackupPsi(char *tpStr)
+{
+ int enable = atoi(tpStr);
+
+ if (enable == 0 || enable == 1)
+ return 0;
+ else
+ return 1;
+}
+
+static int parseSyslogSize(char *tpStr)
+{
+ int syslogSize = atoi(tpStr);
+
+ if (syslogSize >= 0 && syslogSize <= NVRAM_MAX_SYSLOG_SIZE)
+ return 0;
+ else
+ return 1;
+}
+
+
+static int parseMainTp(char *tpStr)
+{
+ int tpNum = atoi(tpStr);
+
+ if (tpNum == 0 || tpNum == 1)
+ return 0;
+ else
+ return 1;
+}
+
+static int charIsHex(char ch)
+{
+ if (((ch >= '0') && (ch <= '9')) ||
+ ((ch >= 'a') && (ch <= 'f')) ||
+ ((ch >= 'A') && (ch <= 'F')))
+ return 1;
+ else
+ return 0;
+}
+
+static int parseGponSN(char *snStr)
+{
+ int i;
+ int ret = 0;
+
+ if(strlen(snStr) == NVRAM_GPON_SERIAL_NUMBER_LEN-1) {
+ for(i=4; i<NVRAM_GPON_SERIAL_NUMBER_LEN-1; ++i) {
+ if(!charIsHex(snStr[i])) {
+ ret = 1;
+ break;
+ }
+ }
+ }
+ else {
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static int parseGponPW(char *pwStr)
+{
+ if(strlen(pwStr) == NVRAM_GPON_PASSWORD_LEN-1)
+ return 0;
+ else
+ return 1;
+}
+
+static int parseWpsDevicePin(char *pinStr)
+{
+ unsigned char accum=0;
+ unsigned char factor[NVRAM_WPS_DEVICE_PIN_LEN]={3,1,3,1,3,1,3,1};
+ int i =0;
+
+ /*Check Length*/
+ if(strlen(pinStr) != NVRAM_WPS_DEVICE_PIN_LEN)
+ return 1;
+
+ /*valid checksum*/
+ for ( i=0; i< NVRAM_WPS_DEVICE_PIN_LEN; i++ )
+ accum += (pinStr[i]-'0')*factor[i];
+
+ if ( (accum%10) ==0 )
+ return 0;
+
+ return 1;
+}
+
+int macNumToStr(unsigned char *macAddr, char *str)
+{
+ if (macAddr == NULL || str == NULL)
+ return 0;
+
+ sprintf(str, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
+ macAddr[0], macAddr[1], macAddr[2],
+ macAddr[3], macAddr[4], macAddr[5]);
+ return 1;
+}
+
+static int gponParamsInitialized(NVRAM_DATA *pNvramData)
+{
+ int i;
+ int erased = 1;
+
+ for(i=0; i<NVRAM_GPON_SERIAL_NUMBER_LEN-1; ++i) {
+ if((pNvramData->gponSerialNumber[i] != (char)0xFF) &&
+ (pNvramData->gponSerialNumber[i] != '\0')) {
+ erased = 0;
+ break;
+ }
+ }
+
+ if(erased) {
+ for(i=0; i<NVRAM_GPON_PASSWORD_LEN-1; ++i) {
+ if((pNvramData->gponPassword[i] != (char)0xFF) &&
+ (pNvramData->gponPassword[i] != '\0')) {
+ erased = 0;
+ break;
+ }
+ }
+ }
+
+ return (erased) ? 0 : 1;
+}
+
+static void getGponBoardParam(void)
+{
+ NVRAM_DATA nvramData;
+ int erased;
+ int i;
+ int writeNvram = 0;
+
+ readNvramData(&nvramData);
+
+ erased = 1;
+ for(i=0; i<NVRAM_GPON_SERIAL_NUMBER_LEN-1; ++i) {
+ if((nvramData.gponSerialNumber[i] != (char)0xFF) &&
+ (nvramData.gponSerialNumber[i] != '\0')) {
+ erased = 0;
+ break;
+ }
+ }
+
+ if(erased) {
+ strcpy(nvramData.gponSerialNumber, DEFAULT_GPON_SN);
+ writeNvram = 1;
+ }
+
+ erased = 1;
+ for(i=0; i<NVRAM_GPON_PASSWORD_LEN-1; ++i) {
+ if((nvramData.gponPassword[i] != (char)0xFF) &&
+ (nvramData.gponPassword[i] != '\0')) {
+ erased = 0;
+ break;
+ }
+ }
+
+ if(erased) {
+ strcpy(nvramData.gponPassword, DEFAULT_GPON_PW);
+ writeNvram = 1;
+ }
+
+ if(writeNvram) {
+ writeNvramData(&nvramData);
+ }
+
+ strcpy(gGponBoardParam[PARAM_IDX_GPON_SN].parameter, nvramData.gponSerialNumber);
+ strcpy(gGponBoardParam[PARAM_IDX_GPON_PW].parameter, nvramData.gponPassword);
+}
+
+int setGponBoardParam(void)
+{
+ NVRAM_DATA nvramData;
+ int ret = 0;
+
+ getGponBoardParam();
+
+ readNvramData(&nvramData);
+
+ if (processPrompt(gGponBoardParam, gNumGponBoardParams)) {
+
+ // At least one field was changed
+ strcpy(nvramData.gponSerialNumber, gGponBoardParam[PARAM_IDX_GPON_SN].parameter);
+ strcpy(nvramData.gponPassword, gGponBoardParam[PARAM_IDX_GPON_PW].parameter);
+
+ // save the buf to nvram
+ writeNvramData(&nvramData);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+
+
+static int gWpsDevicePinParamsInitialized(NVRAM_DATA *pNvramData)
+{
+ int i;
+
+ for(i=0; i<NVRAM_WPS_DEVICE_PIN_LEN; ++i) {
+ if(( (unsigned char)(pNvramData->wpsDevicePin[i]) > 0x39) ||
+ ( (unsigned char)(pNvramData->wpsDevicePin[i]) < 0x30) ) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static void getWpsDevicePinBoardParam(void)
+{
+ NVRAM_DATA nvramData;
+
+ readNvramData(&nvramData);
+
+ if ( gWpsDevicePinParamsInitialized( &nvramData) ) {
+ memcpy(gWpsDevicePinBoardParam[PARAM_IDX_WPS_DEVICE_PIN].parameter,
+ nvramData.wpsDevicePin, NVRAM_WPS_DEVICE_PIN_LEN);
+ (gWpsDevicePinBoardParam[PARAM_IDX_WPS_DEVICE_PIN].parameter)[NVRAM_WPS_DEVICE_PIN_LEN] =
+ '\0';
+ }
+ else {
+ /*Set Default Device Pin*/
+ memcpy(nvramData.wpsDevicePin, DEFAULT_WPS_DEVICE_PIN, NVRAM_WPS_DEVICE_PIN_LEN);
+ writeNvramData(&nvramData);
+
+ memcpy(gWpsDevicePinBoardParam[PARAM_IDX_WPS_DEVICE_PIN].parameter,
+ nvramData.wpsDevicePin,
+ NVRAM_WPS_DEVICE_PIN_LEN);
+ (gWpsDevicePinBoardParam[PARAM_IDX_WPS_DEVICE_PIN].parameter)[NVRAM_WPS_DEVICE_PIN_LEN] =
+ '\0';
+ }
+
+}
+
+int setWpsDevicePinBoardParam(void)
+{
+ NVRAM_DATA nvramData;
+ int ret = 0;
+
+ getWpsDevicePinBoardParam();
+
+ readNvramData(&nvramData);
+
+ if (processPrompt(gWpsDevicePinBoardParam, gNumWpsDevicePinBoardParams)) {
+ memcpy(nvramData.wpsDevicePin,
+ gWpsDevicePinBoardParam[PARAM_IDX_WPS_DEVICE_PIN].parameter,
+ NVRAM_WPS_DEVICE_PIN_LEN);
+ // save the buf to nvram
+ writeNvramData(&nvramData);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+
+static int voiceParamsInitialized(NVRAM_DATA *pNvramData)
+{
+ int rc = 0;
+ NVRAM_DATA nvramData;
+ readNvramData(&nvramData);
+
+ if ( BpSetBoardId(nvramData.szBoardId) == BP_SUCCESS ) {
+ if ( BpGetVoipDspConfig( 0 ) == NULL ) {
+ gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].enabled = FALSE;
+ }
+ else {
+ gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].enabled = TRUE;
+ rc = 1;
+ }
+ }
+
+ return rc;
+}
+
+static void getVoiceBoardParam(void)
+{
+ NVRAM_DATA nvramData;
+ char *ptr;
+ char tmp[10];
+
+ if (g_numVoiceBoardIdNames == 0)
+ g_numVoiceBoardIdNames = BpGetVoiceBoardIds(g_voiceBoardIdNames, MAX_VOICE_BOARD_ID_NAMES);
+
+ ptr = strchr(gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].promptName, '#');
+ if (ptr != NULL) {
+ sprintf(tmp, "%d)", g_numVoiceBoardIdNames - 1);
+ memcpy(ptr, tmp, strlen(tmp));
+ }
+
+ readNvramData(&nvramData);
+
+ memcpy(gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].parameter, nvramData.szVoiceBoardId, NVRAM_BOARD_ID_STRING_LEN);
+ gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].parameter[NVRAM_BOARD_ID_STRING_LEN] = '\0';
+}
+
+int setVoiceBoardParam(void)
+{
+ NVRAM_DATA nvramData;
+ char voiceBoardIdPrompt[1000];
+ int i;
+ char tmp[3];
+ char *voiceBoardIdPromptPtr, *savedVoiceBoardIdPromptPtr;
+ int ret = 0;
+
+ getVoiceBoardParam();
+
+ readNvramData(&nvramData);
+
+ // Create prompt string with voice board ID name selection
+ voiceBoardIdPromptPtr = voiceBoardIdPrompt;
+ for (i = 0; i < g_numVoiceBoardIdNames; i++) {
+ sprintf (tmp, "%d", i);
+ sprintf (voiceBoardIdPromptPtr, "%-17s-- %2s\n", &g_voiceBoardIdNames[i * BP_BOARD_ID_LEN], tmp);
+ voiceBoardIdPromptPtr += strlen(voiceBoardIdPromptPtr);
+ }
+ strcpy (voiceBoardIdPromptPtr, gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].promptName);
+
+ // Save existing prompt string
+ savedVoiceBoardIdPromptPtr = gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].promptName;
+ // Set newly created prompt string
+ gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].promptName = voiceBoardIdPrompt;
+
+ // Convert board ID string to numeric value
+ for (i = 0; i < g_numVoiceBoardIdNames; i++) {
+ if (!strcmp(gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].parameter, &g_voiceBoardIdNames[i * BP_BOARD_ID_LEN])) {
+ sprintf(gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].parameter, "%d", i);
+ }
+ }
+
+ if (processPrompt(gVoiceBoardParam, gNumVoiceBoardParams)) {
+ // At least one field was changed
+ i = atoi(gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].parameter);
+ strcpy(nvramData.szVoiceBoardId, &g_voiceBoardIdNames[i * BP_BOARD_ID_LEN]);
+
+ // save the buf to nvram
+ writeNvramData(&nvramData);
+ ret = 1;
+ }
+
+ // Convert numeric value of voice board ID to string
+ gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].promptName = savedVoiceBoardIdPromptPtr;
+ i = atoi(gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].parameter);
+ strcpy(gVoiceBoardParam[PARAM_IDX_VOICE_BOARD_NAME].parameter, &g_voiceBoardIdNames[i * BP_BOARD_ID_LEN]);
+
+ return ret;
+}
+
+
+//
+// getBoardParam: convert the board param data and put them in the gBoardParam struct
+//
+int getBoardParam(void)
+{
+ NVRAM_DATA nvramData;
+ char *ptr;
+ char tmp[10];
+ int ret = 0;
+
+ if (g_numBoardIdNames == 0)
+ g_numBoardIdNames = BpGetBoardIds(g_boardIdNames, MAX_BOARD_ID_NAMES);
+
+ ptr = strchr(gBoardParam[PARAM_IDX_BOARD_NAME].promptName, '#');
+ if (ptr != NULL) {
+ sprintf(tmp, "%d)", g_numBoardIdNames - 1);
+ memcpy(ptr, tmp, strlen(tmp));
+ }
+
+ readNvramData(&nvramData);
+
+ if(!gGponParamsInitialized) {
+ gGponParamsInitialized = gponParamsInitialized(&nvramData);
+ }
+
+ /*WPS Device Pin Initialized?*/
+ if(!gWpsDevicePinInitialized) {
+ gWpsDevicePinInitialized = gWpsDevicePinParamsInitialized(&nvramData);
+ }
+
+ if (nvramData.ulVersion == -1) {
+ // Set default values
+ nvramData.ulVersion = NVRAM_VERSION_NUMBER;
+ nvramData.szBoardId[0] = '\0';
+ nvramData.ulNumMacAddrs = DEFAULT_MAC_NUM;
+ parsehwaddr(DEFAULT_BOARD_MAC, nvramData.ucaBaseMacAddr);
+ nvramData.ulMainTpNum = DEFAULT_TP_NUM;
+ nvramData.szVoiceBoardId[0] = '\0';
+ nvramData.ulPsiSize = DEFAULT_PSI_SIZE;
+ nvramData.backupPsi = 0;
+ nvramData.ulSyslogSize = 0;
+ writeNvramData(&nvramData);
+ }
+ else if (nvramData.ulVersion != NVRAM_VERSION_NUMBER) {
+ // When upgrading from older bootloader initialize new fields
+ printf("*** Upgrading NVRAM (version %d to version %d) ***\n\n",
+ nvramData.ulVersion, NVRAM_VERSION_NUMBER);
+ nvramData.ulVersion = NVRAM_VERSION_NUMBER;
+ if (nvramData.ulMainTpNum == -1)
+ nvramData.ulMainTpNum = DEFAULT_TP_NUM;
+ if ((nvramData.ulPsiSize == -1) || (nvramData.ulPsiSize == 0))
+ nvramData.ulPsiSize = DEFAULT_PSI_SIZE;
+ nvramData.szVoiceBoardId[0] = '\0';
+ if (nvramData.backupPsi == -1)
+ nvramData.backupPsi = 0;
+ if (nvramData.ulSyslogSize == -1)
+ nvramData.ulSyslogSize = 0;
+ writeNvramData(&nvramData);
+ ret = 1;
+ }
+
+ gVoiceParamsInitialized = voiceParamsInitialized(&nvramData);
+
+ // When backupPsi and syslog were introduced, the NVRAM version number
+ // was not bumped up. So convert -1 (unitialized) to 0 so it looks better.
+ if (nvramData.backupPsi == -1)
+ nvramData.backupPsi = 0;
+ if (nvramData.ulSyslogSize == -1)
+ nvramData.ulSyslogSize = 0;
+
+ strcpy(gBoardParam[PARAM_IDX_BOARD_NAME].parameter, nvramData.szBoardId);
+ sprintf(gBoardParam[PARAM_IDX_NUM_MAC_ADDR].parameter, "%d", nvramData.ulNumMacAddrs);
+ macNumToStr(nvramData.ucaBaseMacAddr, gBoardParam[PARAM_IDX_BASE_MAC_ADDR].parameter);
+ sprintf(gBoardParam[PARAM_IDX_PSI_SIZE].parameter, "%d", nvramData.ulPsiSize);
+ sprintf(gBoardParam[PARAM_IDX_ENABLE_BACKUP_PSI].parameter, "%d", nvramData.backupPsi);
+ sprintf(gBoardParam[PARAM_IDX_SYSLOG_SIZE].parameter, "%d", nvramData.ulSyslogSize);
+ sprintf(gBoardParam[PARAM_IDX_MAIN_THREAD_NUM].parameter, "%d", nvramData.ulMainTpNum);
+
+ return ret;
+}
+
+/* Bob added start to set default board parameters, 11/01/2010 */
+int setDefaultBoardParam(void)
+{
+ NVRAM_DATA nvramData;
+ int ret = 0;
+
+ if (getBoardParam()) {
+ /* New NVRAM version */
+ return ret;
+ }
+
+ readNvramData(&nvramData);
+
+ {
+ // At least one field was changed
+ nvramData.ulVersion = NVRAM_VERSION_NUMBER;
+ strcpy(nvramData.szBoardId, "963281TAN");
+ strcpy(nvramData.szFirmwareUpgradeBoardId, FOXCONN_BOARD_ID);
+ nvramData.ulNumMacAddrs = 10;
+ parsehwaddr("00:00:00:00:00:01", nvramData.ucaBaseMacAddr);
+ nvramData.ulPsiSize = 24;
+ nvramData.backupPsi = 0;
+ nvramData.ulSyslogSize = 0;
+ nvramData.ulMainTpNum = 0;
+
+ // save the buf to nvram
+ writeNvramData(&nvramData);
+ ret = 1;
+ }
+
+ return ret;
+}
+/* Bob added end to set default board parameters, 11/01/2010 */
+
+//
+// setBoardParam: Set the board Id string, mac addresses, psi size, etc...
+//
+int setBoardParam(void)
+{
+ char boardIdPrompt[1000];
+ NVRAM_DATA nvramData;
+ int i;
+ char tmp[3];
+ char *boardIdPromptPtr, *savedBoardIdPromptPtr;
+ int ret = 0;
+
+ if (getBoardParam()) {
+ /* New NVRAM version */
+ return ret;
+ }
+
+ readNvramData(&nvramData);
+
+ // Create prompt string with board ID name selection
+ boardIdPromptPtr = boardIdPrompt;
+ for (i = 0; i < g_numBoardIdNames; i++) {
+ sprintf (tmp, "%d", i);
+ sprintf (boardIdPromptPtr, "%-17s------- %2s\n", &g_boardIdNames[i * BP_BOARD_ID_LEN], tmp);
+ boardIdPromptPtr += strlen(boardIdPromptPtr);
+ }
+ strcpy (boardIdPromptPtr, gBoardParam[PARAM_IDX_BOARD_NAME].promptName);
+
+ // Save existing prompt string
+ savedBoardIdPromptPtr = gBoardParam[PARAM_IDX_BOARD_NAME].promptName;
+ // Set newly created prompt string
+ gBoardParam[PARAM_IDX_BOARD_NAME].promptName = boardIdPrompt;
+
+ // Convert board ID string to numeric value
+ for (i = 0; i < g_numBoardIdNames; i++) {
+ if (!strcmp(gBoardParam[PARAM_IDX_BOARD_NAME].parameter, &g_boardIdNames[i * BP_BOARD_ID_LEN])) {
+ sprintf(gBoardParam[PARAM_IDX_BOARD_NAME].parameter, "%d", i);
+ }
+ }
+
+ if (processPrompt(gBoardParam, gNumBoardParams)) {
+ // At least one field was changed
+ nvramData.ulVersion = NVRAM_VERSION_NUMBER;
+
+ // Convert numeric value of board ID to string
+ i = atoi(gBoardParam[PARAM_IDX_BOARD_NAME].parameter);
+ strcpy(nvramData.szBoardId, &g_boardIdNames[i * BP_BOARD_ID_LEN]);
+
+ nvramData.ulNumMacAddrs = atoi(gBoardParam[PARAM_IDX_NUM_MAC_ADDR].parameter);
+ parsehwaddr(gBoardParam[PARAM_IDX_BASE_MAC_ADDR].parameter, nvramData.ucaBaseMacAddr);
+ nvramData.ulPsiSize = atoi(gBoardParam[PARAM_IDX_PSI_SIZE].parameter);
+ nvramData.backupPsi = atoi(gBoardParam[PARAM_IDX_ENABLE_BACKUP_PSI].parameter);
+ nvramData.ulSyslogSize = atoi(gBoardParam[PARAM_IDX_SYSLOG_SIZE].parameter);
+ nvramData.ulMainTpNum = atoi(gBoardParam[PARAM_IDX_MAIN_THREAD_NUM].parameter);
+
+ // save the buf to nvram
+ writeNvramData(&nvramData);
+ ret = 1;
+ }
+
+ // restore gBoardParam
+ // Convert numeric value of board ID to string
+ gBoardParam[PARAM_IDX_BOARD_NAME].promptName = savedBoardIdPromptPtr;
+ i = atoi(gBoardParam[PARAM_IDX_BOARD_NAME].parameter);
+ strcpy(gBoardParam[PARAM_IDX_BOARD_NAME].parameter, &g_boardIdNames[i * BP_BOARD_ID_LEN]);
+
+ if(gGponParamsInitialized) {
+ printf("\n");
+ ret += setGponBoardParam();
+ }
+
+ if(gWpsDevicePinInitialized) {
+ printf("\n");
+ ret += setWpsDevicePinBoardParam();
+ }
+
+ gVoiceParamsInitialized = voiceParamsInitialized(&nvramData);
+
+ if(gVoiceParamsInitialized) {
+ printf("\n");
+ ret += setVoiceBoardParam();
+ }
+
+ return ret;
+}
+
+void displayBoardParam(void)
+{
+ int i;
+
+ getBoardParam();
+
+ for (i = 0; i < gNumBoardParams; i++) {
+ if( gBoardParam[i].enabled )
+ printf("%s %s \n", gBoardParam[i].promptName, gBoardParam[i].parameter);
+ }
+
+ if(gGponParamsInitialized) {
+ getGponBoardParam();
+
+ for (i = 0; i < gNumGponBoardParams; i++)
+ if( gGponBoardParam[i].enabled )
+ printf("%s \"%s\" \n", gGponBoardParam[i].promptName, gGponBoardParam[i].parameter);
+ }
+
+ /*Show WPS Device PIN */
+ if(gWpsDevicePinInitialized) {
+ getWpsDevicePinBoardParam();
+ if ( gWpsDevicePinBoardParam[PARAM_IDX_WPS_DEVICE_PIN].enabled)
+ printf("%s \"%s\" \n", gWpsDevicePinBoardParam[PARAM_IDX_WPS_DEVICE_PIN].promptName, \
+ gWpsDevicePinBoardParam[PARAM_IDX_WPS_DEVICE_PIN].parameter);
+ }
+
+ if(gVoiceParamsInitialized) {
+ getVoiceBoardParam();
+
+ for (i = 0; i < gNumVoiceBoardParams; i++)
+ if( gVoiceBoardParam[i].enabled )
+ printf("%s %s \n", gVoiceBoardParam[i].promptName, gVoiceBoardParam[i].parameter);
+ }
+}
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_cmd.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_cmd.c
new file mode 100755
index 0000000..111e73f
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_cmd.c
@@ -0,0 +1,1878 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ *
+ * bcm63xx board specific routines and commands.
+ *
+ * by: seanl
+ *
+ * April 1, 2002
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "bcm63xx_util.h"
+#include "flash_api.h"
+#include "jffs2.h"
+
+/* Foxconn add start by Cliff Wang, 03/23/2010 */
+#include "tftpd.h"
+
+#include "net_nmrp.h"
+
+
+extern int nmrp_server_detected;
+extern unsigned long cfe_sdramsize;
+extern int ui_init_tftpdcmds(void);
+int verify_checksum(char *buf, unsigned long buf_len, unsigned long chksum);
+/* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+#define je16_to_cpu(x) ((x).v16)
+#define je32_to_cpu(x) ((x).v32)
+#define FLASH_STAGING_BUFFER BOARD_IMAGE_DOWNLOAD_ADDRESS
+#define FLASH_STAGING_BUFFER_SIZE BOARD_IMAGE_DOWNLOAD_SIZE
+
+extern int decompressLZMA(unsigned char *in, unsigned insize, unsigned char *out, unsigned outsize);
+
+// global
+int g_processing_cmd = 0;
+
+char fakeConsole[2] = " ";
+
+/* Foxconn add start by Jenny Zhao, 07/02/2008*/
+struct image_header
+{
+ unsigned long magic; /* magic */
+ unsigned long header_len; /* Length of header */
+ unsigned char reserved[8];
+ unsigned long kernel_chksum; /* Kernel image chksum */
+ unsigned long rootfs_chksum; /* rootfs image chksum */
+ unsigned long kernel_len; /* Length of kernel */
+ unsigned long rootfs_len; /* Length of rootfs */
+ unsigned long image_chksum; /* checksum across length of image */
+ unsigned long header_chksum; /* checksum across length of header */
+};
+
+#define swap32(val) \
+ ((unsigned int)( \
+ (((unsigned int)(val) & (unsigned int)0x000000ffUL)) | \
+ (((unsigned int)(val) & (unsigned int)0x0000ff00UL)) | \
+ (((unsigned int)(val) & (unsigned int)0x00ff0000UL)) | \
+ (((unsigned int)(val) & (unsigned int)0xff000000UL)) ))
+
+/* pling added 12/04/2008, define the Foxconn board ID length */
+#define FOXCONN_BOARD_ID_LEN 64
+/* Foxconn add end by Jenny Zhao, 07/02/2008*/
+
+static int ui_cmd_set_board_param(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int ret = 0;
+ int i = 0;
+ int reset = 0;
+
+ if(!argc)
+ {
+ reset += setBoardParam();
+ }
+
+ while(argc && !ret)
+ {
+ if(!strcmp(argv[i], "g"))
+ {
+ reset += setGponBoardParam();
+ }
+ else {
+ /*Setup WPS Device Pin*/
+ if(!strcmp(argv[i], "w"))
+ {
+ reset += setWpsDevicePinBoardParam();
+ }
+ else
+ {
+ ret = -1;
+ }
+ }
+
+ argc--;
+ i++;
+ }
+
+ if(reset)
+ softReset();
+
+ return ret;
+}
+
+static int ui_cmd_reset(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ softReset();
+ return 0;
+}
+
+// return 0 if 'y'
+int yesno(void)
+{
+ char ans[5];
+
+ printf(" (y/n):");
+ console_readline ("", ans, sizeof (ans));
+ if (ans[0] != 'y')
+ return -1;
+
+ return 0;
+}
+
+// erase Persistent sector
+static int ui_cmd_erase_psi(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ printf("Erase persisten storage data?");
+ if (yesno())
+ return -1;
+
+ kerSysErasePsi();
+
+ return 0;
+}
+
+static int ui_cmd_erase_nand(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+
+#if (INC_NAND_FLASH_DRIVER==1)
+ char *flag;
+ int i, blk_end;
+
+ flag = cmd_getarg(cmd,0);
+
+ if (!flag)
+ {
+ printf("'e b' to reinitialize NAND flash or 'e a' to erase kernel\n");
+ return 0;
+ }
+
+ switch (*flag)
+ {
+ case 'b':
+ printf("Reinitialize NAND flash?");
+ if (yesno())
+ return 0;
+ printf("\nNow think carefully. Do you really,\n"
+ "really want to reinitialize the NAND flag?");
+ if (yesno())
+ return 0;
+ flash_sector_erase_int(NAND_REINIT_FLASH);
+ break;
+ case 'a':
+ printf("Erase NAND flash? The modem will not be able to boot from "
+ "flash");
+ if (yesno())
+ return 0;
+
+ blk_end = flash_get_numsectors();
+ for (i = 1; i < blk_end; i++)
+ {
+ printf(".");
+ flash_sector_erase_int(i);
+ }
+ printf("\n");
+ break;
+ case 's':
+ {
+ extern void dump_spare(void);
+ dump_spare();
+ }
+ break;
+
+ case 'r':
+ {
+ extern unsigned char *mem_topofmem;
+ unsigned char *buf = (unsigned char *) mem_topofmem + 1024;
+ char *pszLen = cmd_getarg(cmd, 2);
+ int len = (pszLen) ? atoi(pszLen) : 64;
+ char *pszBlk = cmd_getarg(cmd, 1);
+ if( flash_read_buf(atoi(pszBlk), 0, buf, 16 * 1024) > 0 )
+ {
+ void ui_dumpaddr( unsigned char *pAddr, int nLen );
+ printf("block read into buffer at 0x%8.8lx\n", (unsigned long)buf);
+ ui_dumpaddr(buf, len); /* dump first few bytes */
+ }
+ else
+ printf("block NOT read into buffer at 0x%8.8lx\n",(unsigned long)buf);
+ /* Can break into JTAG now to view entire block contents. */
+ }
+ break;
+ default:
+ printf("Erase [n]vram, [p]ersistent storage or [a]ll flash except bootrom\nusage: e [n/p/a]\n");
+ return 0;
+ }
+#elif (INC_SPI_PROG_NAND==1)
+ char *flag;
+ int i, blk_end;
+
+ flash_change_flash_type(FLASH_IFC_NAND);
+
+ flag = cmd_getarg(cmd,0);
+
+ if (!flag)
+ {
+ printf("'n b' to reinitialize NAND flash or 'n a' to erase kernel on NAND\n");
+ goto finish;
+ }
+
+ switch (*flag)
+ {
+ case 'b':
+ printf("Reinitialize NAND flash?");
+ if (yesno())
+ goto finish;
+ printf("\nNow think carefully. Do you really,\n"
+ "really want to reinitialize the NAND flag?");
+ if (yesno())
+ goto finish;
+ flash_sector_erase_int(NAND_REINIT_FLASH);
+ break;
+ case 'a':
+ printf("Erase NAND flash? The modem will not be able to boot from "
+ "flash");
+ if (yesno())
+ goto finish;
+
+ blk_end = flash_get_numsectors();
+ for (i = 1; i < blk_end; i++)
+ {
+ printf(".");
+ flash_sector_erase_int(i);
+ }
+ printf("\n");
+ break;
+ case 's':
+ {
+ extern void dump_spare(void);
+ dump_spare();
+ }
+ break;
+
+ case 'r':
+ {
+ extern unsigned char *mem_topofmem;
+ unsigned char *buf = (unsigned char *) mem_topofmem + 1024;
+ char *pszBlk = cmd_getarg(cmd, 1);
+ if( flash_read_buf(atoi(pszBlk), 0, buf, 16 * 1024) > 0 )
+ {
+ void ui_dumpaddr( unsigned char *pAddr, int nLen );
+ printf("block read into buffer at 0x%8.8lx\n", (unsigned long)buf);
+ ui_dumpaddr(buf, 64); /* dump first few bytes */
+ }
+ else
+ printf("block NOT read into buffer at 0x%8.8lx\n",(unsigned long)buf);
+ /* Can break into JTAG now to view entire block contents. */
+ }
+ break;
+ default:
+ printf("Erase [n]vram, [p]ersistent storage or [a]ll flash except bootrom on NAND\nusage: n [n/p/a]\n");
+ }
+finish:
+ flash_change_flash_type(FLASH_IFC_SPI);
+
+#endif
+
+ return 0;
+}
+
+// erase some sectors
+static int ui_cmd_erase(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+
+ //FILE_TAG cfeTag;
+ PFILE_TAG pTag;
+ char *flag;
+ int i, blk_start, blk_end;
+
+ flag = cmd_getarg(cmd,0);
+
+ if (!flag)
+ {
+ printf("Erase [n]vram, [p]ersistent storage or [a]ll flash except bootrom\nusage: e [n/p/a]\n");
+ return 0;
+ }
+
+ switch (*flag)
+ {
+ case 'b':
+ printf("Erase boot loader?");
+ if (yesno())
+ return 0;
+ printf("\nNow think carefully. Do you really,\n"
+ "really want to erase the boot loader?");
+ if (yesno())
+ return 0;
+ flash_sector_erase_int(0);
+ break;
+ case 'n':
+ printf("Erase nvram?");
+ if (yesno())
+ return 0;
+ kerSysEraseNvRam();
+ softReset();
+ break;
+ case 'a':
+
+ printf("Erase all flash (except bootrom)?");
+ if (yesno())
+ return 0;
+
+ blk_end = flash_get_numsectors();
+ if ((pTag = getTagFromPartition(1)) != NULL)
+ blk_start = flash_get_blk(atoi(pTag->rootfsAddress) + BOOT_OFFSET);
+ else // just erase all after cfe
+ {
+ FLASH_ADDR_INFO flash_info;
+
+ kerSysFlashAddrInfoGet(&flash_info);
+ for( blk_start = 0, i = 0; i<flash_info.flash_rootfs_start_offset &&
+ blk_start < blk_end; blk_start++ )
+ {
+ i += flash_get_sector_size(blk_start);
+ }
+ printf("No image tag found. Erase the blocks start at [%d]\n",
+ blk_start);
+ }
+ if( blk_start > 0 )
+ {
+ for (i = blk_start; i < blk_end; i++)
+ {
+ printf(".");
+ flash_sector_erase_int(i);
+ }
+ printf("\n");
+ }
+
+ /* Preserve the NVRAM fields that are used in the 'b' command. */
+ softReset();
+ break;
+ case 'p':
+ ui_cmd_erase_psi(cmd,argc,argv);
+ break;
+ default:
+ printf("Erase [n]vram, [p]ersistent storage or [a]ll flash except bootrom\nusage: e [n/p/a]\n");
+ return 0;
+ }
+
+ return 0;
+}
+
+
+static int loadRaw(char *hostImageName, uint8_t *ptr)
+{
+ cfe_loadargs_t la;
+ int res;
+
+ printf("Loading %s ...\n", hostImageName);
+
+ // tftp only
+ la.la_filesys = "tftp";
+ la.la_filename = hostImageName;
+ la.la_device = NULL;
+ la.la_address = (long)ptr;
+ la.la_options = NULL;
+ la.la_maxsize = FLASH_STAGING_BUFFER_SIZE;
+ la.la_flags = LOADFLG_SPECADDR;
+
+ res = bcm63xx_cfe_rawload(&la);
+ if (res < 0)
+ {
+ ui_showerror(res, "Loading failed.");
+ return res;
+ }
+ printf("Finished loading %d bytes\n", res);
+
+ return res;
+}
+
+// flash the image
+static int ui_cmd_flash_image(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char hostImageName[BOOT_FILENAME_LEN + BOOT_IP_LEN];
+ char *imageName;
+ int res;
+ uint8_t *ptr = (uint8_t *) KERNADDR(FLASH_STAGING_BUFFER);
+
+ g_processing_cmd = 1;
+
+ imageName = cmd_getarg(cmd, 0);
+
+ if (imageName)
+ {
+ if (strchr(imageName, ':'))
+ strcpy(hostImageName, imageName);
+ else
+ {
+ strcpy(hostImageName, bootInfo.hostIp);
+ strcat(hostImageName, ":");
+ strcat(hostImageName, imageName);
+ }
+ }
+ else // use default flash file name
+ {
+ strcpy(hostImageName, bootInfo.hostIp);
+ strcat(hostImageName, ":");
+ strcat(hostImageName, bootInfo.flashFileName);
+ }
+
+ if ((res = loadRaw(hostImageName, ptr)) < 0)
+ {
+ g_processing_cmd = 0;
+ return res;
+ }
+
+ // check and flash image
+ res = flashImage(ptr);
+
+ if( res == 0 )
+ {
+ char *p;
+ NVRAM_DATA nvramData;
+
+ readNvramData(&nvramData);
+
+ for( p = nvramData.szBootline; p[2] != '\0'; p++ ) {
+ if( p[0] == 'r' && p[1] == '=' && p[2] == 'h' )
+ {
+ /* Change boot source to "boot from flash". */
+ p[2] = 'f';
+ writeNvramData(&nvramData);
+ break;
+ }
+ }
+ softReset();
+ }
+
+ g_processing_cmd = 0;
+ return( res );
+}
+
+static int ui_cmd_write_chk_image(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char hostImageName[BOOT_FILENAME_LEN + BOOT_IP_LEN];
+ char *imageName;
+ uint8_t *ptr = (uint8_t *) KERNADDR(FLASH_STAGING_BUFFER);
+ int res;
+ struct image_header *header;
+ unsigned long image_len, image_chksum;
+
+ unsigned long header_len = 0;
+ unsigned long board_id_len = 0;
+ char board_id[FOX_BOARD_ID_MAX_LEN];
+ uint8_t *tmp;
+
+ g_processing_cmd = 1;
+
+ imageName = cmd_getarg(cmd, 0);
+ if (!imageName)
+ return ui_showusage(cmd);
+
+ if (strchr(imageName, ':'))
+ strcpy(hostImageName, imageName);
+ else
+ {
+ strcpy(hostImageName, bootInfo.hostIp);
+ strcat(hostImageName, ":");
+ strcat(hostImageName, imageName);
+ }
+
+ if ((res = loadRaw(hostImageName, ptr)) < 0)
+ {
+ g_processing_cmd = 0;
+ return res;
+ }
+
+ /* check chk file */
+ header = (struct image_header *)ptr;
+ header_len = swap32(header->header_len);
+ image_len = swap32(header->kernel_len);
+ image_chksum = swap32(header->kernel_chksum);
+ board_id_len = header_len - sizeof(struct image_header);
+
+ memset(board_id, 0, sizeof(board_id));
+ memcpy(board_id, header+1, board_id_len);
+
+ printf("total:%d header:%d kernel:%d \n", res, header_len, image_len);
+
+ tmp = ptr;
+ ptr += header_len;
+ res -= header_len;
+
+ if (verify_checksum((char*)ptr, image_len, image_chksum)) {
+ printf("fail to comapre checksum ... \n ");
+ return CFE_ERR_BADIMAGE;
+ }
+
+ memcpy(tmp, ptr, res);
+
+ // check and flash image
+ res = writeWholeImage(tmp, res);
+
+ printf("Finished flashing image.\n");
+/*
+ if (res == 0)
+ {
+ softReset();
+ }
+*/
+ g_processing_cmd = 0;
+ return( res );
+}
+
+// write the whole image
+static int ui_cmd_write_whole_image(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char hostImageName[BOOT_FILENAME_LEN + BOOT_IP_LEN];
+ char *imageName;
+ uint8_t *ptr = (uint8_t *) KERNADDR(FLASH_STAGING_BUFFER);
+ int res;
+
+ g_processing_cmd = 1;
+
+ imageName = cmd_getarg(cmd, 0);
+ if (!imageName)
+ return ui_showusage(cmd);
+
+ if (strchr(imageName, ':'))
+ strcpy(hostImageName, imageName);
+ else
+ {
+ strcpy(hostImageName, bootInfo.hostIp);
+ strcat(hostImageName, ":");
+ strcat(hostImageName, imageName);
+ }
+
+ if ((res = loadRaw(hostImageName, ptr)) < 0)
+ {
+ g_processing_cmd = 0;
+ return res;
+ }
+
+ // check and flash image
+ res = writeWholeImage(ptr, res);
+
+ printf("Finished flashing image.\n");
+
+ if (res == 0)
+ {
+ softReset();
+ }
+
+ g_processing_cmd = 0;
+ return( res );
+}
+
+
+static int ui_cmd_flash_router_image(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char hostImageName[BOOT_FILENAME_LEN + BOOT_IP_LEN];
+ char *imageName;
+ uint8_t *ptr = (uint8_t *) KERNADDR(FLASH_STAGING_BUFFER);
+
+#if (INC_NAND_FLASH_DRIVER==1)
+ uint8_t *tmp;
+#endif
+
+ int res;
+
+ char board_id[FOX_BOARD_ID_MAX_LEN]; //Silver
+ int update=0;
+ char board_id_test[PROJECT_ID_LEN];
+
+#if (INC_NAND_FLASH_DRIVER==1)
+ NVRAM_DATA nvramData;
+#endif
+
+ imageName = cmd_getarg(cmd, 0);
+ if (!imageName)
+ return ui_showusage(cmd);
+
+ if (strchr(imageName, ':'))
+ strcpy(hostImageName, imageName);
+ else
+ {
+ strcpy(hostImageName, "");
+ strcat(hostImageName, ":");
+ strcat(hostImageName, "");
+ }
+
+ set_tftpd_state(TFTPD_STATE_WAIT_IMAGE);
+ if ((res = loadRaw(hostImageName, ptr)) < 0) {
+ printf("fail to load raw file ... \n");
+ return res;
+ }
+
+ if ( nmrp_server_detected == 0)
+ {
+ set_tftpd_state(TFTPD_STATE_OFF); // Foxconn added to turn on RED.
+ setPowerOnLedOn(); // Foxconn added to turn on RED.
+ }
+
+ /* Foxconn add start by Jenny Zhao, 07/02/2008*/
+ if (1) {
+ struct image_header *header;
+ unsigned long image_len, image_chksum;
+
+ unsigned long header_len = 0;
+ unsigned long board_id_len = 0;
+
+ header = (struct image_header *)ptr;
+ header_len = swap32(header->header_len);
+ image_len = swap32(header->kernel_len);
+ image_chksum = swap32(header->kernel_chksum);
+ /* Check Board ID first */
+ board_id_len = header_len - sizeof(struct image_header);
+ memset(board_id, 0, sizeof(board_id));
+ //for(i=0;i<board_id_len;i++)
+ /* printf("copy board id ... \n"); */
+
+ //memcpy(board_id, board_id_test, board_id_len);
+#if (INC_NAND_FLASH_DRIVER==1)
+ readNvramData(&nvramData);
+ if ( nvramData.szFirmwareUpgradeBoardId != NULL )
+ memcpy(board_id_test, nvramData.szFirmwareUpgradeBoardId, PROJECT_ID_LEN);
+#else
+ kerSysReadFromFlash(board_id_test, BOARD_DATA_ADDR, PROJECT_ID_LEN);
+#endif
+ /* printf("bboard id is (%s)\n", board_id_test); */
+
+ memcpy(board_id, header+1, board_id_len);
+
+ /* printf("iboard id is (%s)\n", board_id); */
+
+/* disable board_id checking
+ if (verify_board_id(board_id)) {
+ printf("Check board id fail: (%s)\n", board_id);
+ return CFE_ERR_BADIMAGE;
+ }
+*/
+ /* Check image checksum */
+#ifdef _DEBUG
+ xprintf("len = 0x%08X\n", image_len);
+ xprintf("chksum = 0x%08X\n", image_chksum);
+ xprintf("header_len = 0x%08X\n", header_len);
+#endif
+
+#if (INC_NAND_FLASH_DRIVER==1)
+ tmp = ptr;
+ res -= header_len;
+#endif
+
+ ptr += header_len;
+
+ if (verify_checksum((char*)ptr, image_len, image_chksum)) {
+ printf("fail to comapre checksum ... \n ");
+ return CFE_ERR_BADIMAGE;
+ }
+ }
+
+ /* Foxconn add end by Jenny Zhao, 07/02/2008*/
+ if(nmrp_server_detected==1) // in NMRP mode
+ {
+ printf(">>> kerSysBcmImageSet= 0x%x\n", FLASH_IMAGE_START_ADDR);
+#if (INC_NAND_FLASH_DRIVER==1)
+ memcpy(tmp, ptr, res);
+ if ((res = writeWholeImage(tmp, res) )!= 0)
+#else
+ if ((res = kerSysBcmImageSet(FLASH_IMAGE_START_ADDR, ptr, res, 0)) != 0)
+#endif
+ printf("Failed to flash image. Error: %d\n", res);
+ else
+ {
+ /* Foxconn added start, Silver Shih for burn board Id */
+ if( strlen(board_id) < FOX_BOARD_ID_MAX_LEN)
+ {
+ if(strcmp(board_id_test, board_id) != 0)
+ //if (strcmp((char *)BOARD_DATA_ADDR, board_id) != 0)
+ {
+ //printf("board id not match, addr:0x%x\n", BOARD_DATA_ADDR);
+ //5 is indicated to burn board id
+#if (INC_NAND_FLASH_DRIVER==0)
+ kerSysBcmImageSet(BOARD_DATA_ADDR, (unsigned char *)board_id, strlen(board_id)+1 , 5);
+#endif
+ }
+ }
+ /* Foxconn added end, Silver Shih for burn board Id */
+
+ update=1;
+ printf("Finished flashing image in NMRP mode.\n");
+ }
+ }
+ /* Foxconn added start pling 12/04/2008, for 'tftpd' */
+#if (INC_NAND_FLASH_DRIVER==0)
+ else if ((res = kerSysBcmImageSet(FLASH_IMAGE_START_ADDR, ptr, res, 0)) != 0)
+ printf("Failed to flash image. Error: %d\n", res);
+#endif
+ else
+ printf("finishing flash image for flashimage command ... \n");
+
+ /* Foxconn added end pling 12/04/2008 */
+ if (res == 0)
+ {
+ char *p;
+ NVRAM_DATA nvramData;
+
+ readNvramData(&nvramData);
+
+ memcpy(nvramData.szFirmwareUpgradeBoardId, board_id, strlen(board_id));
+
+ for( p = nvramData.szBootline; p[2] != '\0'; p++ ) {
+ if( p[0] == 'r' && p[1] == '=' && p[2] == 'h' )
+ {
+ /* Change boot source to "boot from flash". */
+ p[2] = 'f';
+ //writeNvramData(&nvramData);
+ break;
+ }
+ }
+ writeNvramData(&nvramData);
+ // softReset(); //remove by EricHuang
+ }
+
+ if (nmrp_server_detected==1 && update==1) //NMRP mode
+ {
+ // Restore to factory default.
+ printf("try to restore to default, addr=0x%x\n", BOARD_FOXNVRAM_ADDR);
+#if (INC_NAND_FLASH_DRIVER==0)
+ kerSysBcmImageSet(BOARD_FOXNVRAM_ADDR, (unsigned char *)"", 0x10000 , 5);
+#endif
+ }
+
+ return( res );
+}
+
+/************************************************************************
+ * cfe_go(la)
+ *
+ * Starts a previously loaded program. cfe_loadargs.la_entrypt
+ * must be set to the entry point of the program to be started
+ *
+ * Input parameters:
+ * la - loader args
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+void cfe_go(cfe_loadargs_t *la)
+{
+ if (la->la_entrypt == 0) {
+ xprintf("No program has been loaded.\n");
+ return;
+ }
+
+ if (net_getparam(NET_DEVNAME)) {
+ xprintf("Closing network.\n");
+ net_uninit();
+ }
+
+ xprintf("Starting program at 0x%p\n",la->la_entrypt);
+
+ setPowerOnLedOn();
+
+ cfe_start(la->la_entrypt);
+}
+
+static int bootImage(char *fileSys, char *device, int zflag, char *imageName)
+{
+ cfe_loadargs_t la;
+ int res;
+
+ // elf only
+ la.la_filesys = fileSys;
+ la.la_filename = imageName;
+ la.la_device = device;
+ la.la_options = 0;
+ la.la_maxsize = 0;
+ la.la_address = 0;
+ la.la_flags = zflag;
+
+ res = bcm63xx_cfe_elfload(&la);
+ if (res != 0)
+ return res;
+
+ if (la.la_flags & LOADFLG_NOISY)
+ xprintf("Entry at 0x%p\n",la.la_entrypt);
+ if ((la.la_flags & LOADFLG_EXECUTE) && (la.la_entrypt != 0)) {
+ cfe_go(&la);
+ }
+
+ return res;
+}
+
+// Compressed image head format in Big Endia:
+// 1) Text Start address: 4 bytes
+// 2) Program Entry point: 4 bytes
+// 3) Compress image Length: 4 bytes
+// 4) Compress data starts: compressed data
+static int bootCompressedImage(unsigned int *puiCmpImage, int retry)
+{
+ unsigned char *pucSrc;
+ unsigned char *pucDst;
+ unsigned char *pucEntry;
+ unsigned int dataLen;
+ int ret = 0;
+ cfe_loadargs_t la;
+
+ if( (unsigned long) puiCmpImage > FLASH_BASE )
+ {
+ /* Boot compressed image from flash. */
+ unsigned int *puiOrigCmpImage = puiCmpImage;
+ unsigned int *puiNewCmpImage = NULL;
+ unsigned int *puiOldCmpImage = NULL;
+ unsigned int *puiFs = NULL;
+ PFILE_TAG pTag1 = getTagFromPartition(1);
+ PFILE_TAG pTag2 = getTagFromPartition(2);
+ PFILE_TAG pCurTag = NULL;
+ unsigned int *puiImg= NULL;
+ int nImgLen = 0;
+ unsigned long ulCrc, ulImgCrc;
+
+ if( pTag1 && pTag2 )
+ {
+ /* Two images are on flash. Determine which one is being booted. */
+ PFILE_TAG pNewTag = NULL;
+ PFILE_TAG pOldTag = NULL;
+ int seq1 = atoi(pTag1->imageSequence);
+ int seq2 = atoi(pTag2->imageSequence);
+
+ if( seq1 > seq2 )
+ {
+ pNewTag = pTag1;
+ pOldTag = pTag2;
+ }
+ else
+ {
+ pNewTag = pTag2;
+ pOldTag = pTag1;
+ }
+
+ puiNewCmpImage = (unsigned int *)
+ (atoi(pNewTag->kernelAddress) + BOOT_OFFSET);
+ puiOldCmpImage = (unsigned int *)
+ (atoi(pOldTag->kernelAddress) + BOOT_OFFSET);
+
+ if( puiOrigCmpImage == puiOldCmpImage )
+ {
+ printf("Booting from previous image (0x%8.8lx) ...\n",
+ (unsigned long) atoi(pOldTag->rootfsAddress) +
+ BOOT_OFFSET - TAG_LEN);
+ pCurTag = pOldTag;
+ }
+ else
+ {
+ printf("Booting from latest image (0x%8.8lx) ...\n",
+ (unsigned long) atoi(pNewTag->rootfsAddress) +
+ BOOT_OFFSET - TAG_LEN);
+ pCurTag = pNewTag;
+ }
+ }
+ else
+ if( pTag1 || pTag2 )
+ {
+ /* Only one image on flash. */
+ pCurTag = (pTag1) ? pTag1 : pTag2;
+ printf("Booting from only image (0x%8.8lx) ...\n",
+ (unsigned long) atoi(pCurTag->rootfsAddress) +
+ BOOT_OFFSET - TAG_LEN);
+ }
+ else
+ {
+ /* No image on flash. */
+ printf("No valid boot image\n");
+ ret = -1;
+ }
+
+ if( ret == 0 )
+ {
+ /* Copy compressed image to SDRAM. */
+ extern unsigned char *mem_topofmem;
+ FLASH_ADDR_INFO info;
+ unsigned char *pDest = (unsigned char *) mem_topofmem + 1024;
+ unsigned char *pImgEnd;
+
+ kerSysFlashAddrInfoGet( &info );
+ pImgEnd = flash_get_memptr( info.flash_meta_start_blk );
+ kerSysReadFromFlash( pDest, (unsigned long) puiCmpImage,
+ (unsigned long) pImgEnd - (unsigned long) puiCmpImage );
+
+ puiCmpImage = (unsigned int *) pDest;
+
+ /* Copy file system to SDRAM. */
+ pDest += (unsigned long) pImgEnd - (unsigned long)
+ puiOrigCmpImage + 1024;
+ kerSysReadFromFlash( pDest, (unsigned long)
+ atoi(pCurTag->rootfsAddress) + BOOT_OFFSET,
+ atoi(pCurTag->rootfsLen));
+
+ puiFs = (unsigned int *) pDest;
+
+ pucDst = (unsigned char *) *puiCmpImage;
+ pucEntry = (unsigned char *) *(puiCmpImage + 1);
+ dataLen = (unsigned int) *(puiCmpImage + 2);
+ pucSrc = (unsigned char*) (puiCmpImage + 3);
+
+ printf("Code Address: 0x%08X, Entry Address: 0x%08x\n",
+ (unsigned int) pucDst, (unsigned int) pucEntry);
+
+
+ /* Check Linux file system CRC */
+ ulImgCrc = *(unsigned long *) (pCurTag->imageValidationToken +
+ CRC_LEN);
+ if( ulImgCrc )
+ {
+ if( puiFs )
+ puiImg = puiFs;
+ else
+ {
+ puiImg = (unsigned int *) (atoi(pCurTag->rootfsAddress) +
+ BOOT_OFFSET);
+ }
+ nImgLen = atoi(pCurTag->rootfsLen);
+
+ ulCrc = CRC32_INIT_VALUE;
+ ulCrc = getCrc32((unsigned char *) puiImg, (UINT32) nImgLen, ulCrc);
+ if( ulCrc != ulImgCrc)
+ {
+ printf("Linux file system CRC error. Corrupted image?\n");
+ ret = -1;
+ }
+ }
+
+ /* Check Linux kernel CRC */
+ ulImgCrc = *(unsigned long *) (pCurTag->imageValidationToken +
+ (CRC_LEN * 2));
+ if( ulImgCrc )
+ {
+ puiImg = (unsigned int *) puiCmpImage;
+ nImgLen = atoi(pCurTag->kernelLen);
+
+ ulCrc = CRC32_INIT_VALUE;
+ ulCrc = getCrc32((unsigned char *) puiImg, (UINT32) nImgLen, ulCrc);
+ if( ulCrc != ulImgCrc)
+ {
+ printf("Linux kernel CRC error. Corrupted image?\n");
+ ret = -1;
+ }
+ }
+
+ if( ret == 0 )
+ {
+ ret = decompressLZMA(pucSrc, dataLen, pucDst, 23*1024*1024);
+ if (ret != 0)
+ printf("Failed to decompress image. Corrupted image?\n");
+ }
+
+ if (ret != 0)
+ {
+ /* Try to boot from the other flash image, if one exists. */
+ if( retry == TRUE && pTag1 && pTag2 )
+ {
+ int blk = 0;
+ unsigned char *pBase = flash_get_memptr(0);
+ unsigned int *flash_addr_kernel;
+ FLASH_ADDR_INFO flash_info;
+
+ /* The boot image is bad. Erase the sector with the tag so
+ * the image is not tried in subsequent boots.
+ */
+ kerSysFlashAddrInfoGet(&flash_info);
+ if( pCurTag == pTag1 )
+ {
+ blk = flash_get_blk((int)(pBase +
+ flash_info.flash_rootfs_start_offset));
+ }
+ else
+ if( pCurTag == pTag2 )
+ {
+ blk = flash_get_blk((int) (pBase +
+ (flash_get_total_size()/2)));
+ }
+
+ if( blk )
+ flash_sector_erase_int(blk);
+
+ /* Boot from the other flash image. */
+ if( puiOrigCmpImage == puiOldCmpImage )
+ flash_addr_kernel = puiNewCmpImage;
+ else
+ flash_addr_kernel = puiOldCmpImage;
+
+ ret = bootCompressedImage( flash_addr_kernel, FALSE );
+ }
+ }
+ else
+ {
+ printf("Decompression OK!\n");
+ la.la_entrypt = (long) pucEntry;
+ printf("Entry at 0x%p\n",la.la_entrypt);
+ cfe_go(&la); // never return...
+ }
+
+ }
+ }
+ else
+ {
+ /* Boot compressed image that was downloaded to RAM. */
+ pucDst = (unsigned char *) *puiCmpImage;
+ pucEntry = (unsigned char *) *(puiCmpImage + 1);
+ dataLen = (unsigned int) *(puiCmpImage + 2);
+ pucSrc = (unsigned char*) (puiCmpImage + 3);
+
+ printf("Code Address: 0x%08X, Entry Address: 0x%08x\n",
+ (unsigned int) pucDst, (unsigned int) pucEntry);
+
+ ret = decompressLZMA(pucSrc, dataLen, pucDst, 23*1024*1024);
+ if (ret == 0)
+ {
+ printf("Decompression OK!\n");
+ la.la_entrypt = (long) pucEntry;
+ printf("Entry at 0x%p\n",la.la_entrypt);
+ cfe_go(&la); // never return...
+ }
+ else
+ printf("Failed on decompression. Corrupted image?\n");
+ }
+
+ return ret;
+}
+
+static int bootNandImageFromRootfs(int start_blk, int end_blk)
+{
+ extern unsigned char *mem_topofmem;
+ char fname[] = NAND_FLASH_BOOT_IMAGE_NAME;
+ int fname_len = strlen(fname);
+ int len = flash_get_sector_size(0);
+ unsigned char *buf = (unsigned char *) mem_topofmem + 1024;
+ unsigned char *pDest = (unsigned char *) buf + len;
+ unsigned long *pulDest = (unsigned long *) pDest;
+ unsigned char *p;
+ unsigned long version = 0;
+ unsigned long ino = 0;
+ int i, done;
+ struct jffs2_raw_dirent *pdir;
+ struct jffs2_raw_inode *pino;
+ int ret = 0;
+
+ /* Find the directory entry. */
+ for( i = start_blk, done = 0; i < end_blk && done == 0; i++ )
+ {
+ if( flash_read_buf(i, 0, buf, len) > 0 )
+ {
+ p = buf;
+ while( p < buf + len )
+ {
+ pdir = (struct jffs2_raw_dirent *) p;
+ if( je16_to_cpu(pdir->magic) == JFFS2_MAGIC_BITMASK )
+ {
+ if( je16_to_cpu(pdir->nodetype) == JFFS2_NODETYPE_DIRENT &&
+ fname_len == pdir->nsize &&
+ !memcmp(fname, pdir->name, fname_len) )
+ {
+ if( je32_to_cpu(pdir->version) > version )
+ {
+ if( (ino = je32_to_cpu(pdir->ino)) != 0 )
+ {
+ version = je32_to_cpu(pdir->version);
+
+ /* Setting 'done = 1' assumes there is only one
+ * version of the directory entry. This may not
+ * be correct if the file is updated after it
+ * was initially flashed.
+ *
+ * TBD. Look for a higher version of the
+ * directory entry without searching the entire
+ * flash part.
+ */
+ done = 1;
+ break;
+ }
+ }
+ }
+
+ p += (je32_to_cpu(pdir->totlen) + 0x03) & ~0x03;
+ }
+ else
+ break;
+ }
+ }
+ }
+
+ if( version )
+ {
+ unsigned char *pucSrc;
+ unsigned char *pucDst;
+ unsigned char *pucEntry;
+ unsigned int dataLen;
+ unsigned long cur_isize = 0;
+
+ /* Get the file contents. */
+ for( i = start_blk, done = 0; i < end_blk && done == 0; i++ )
+ {
+ if( flash_read_buf(i, 0, buf, len) > 0 )
+ {
+ p = buf;
+ while( p < buf + len )
+ {
+ pino = (struct jffs2_raw_inode *) p;
+ if( je16_to_cpu(pino->magic) == JFFS2_MAGIC_BITMASK )
+ {
+ if(je16_to_cpu(pino->nodetype)==JFFS2_NODETYPE_INODE &&
+ je32_to_cpu(pino->ino) == ino)
+ {
+ unsigned long size = je32_to_cpu(pino->dsize);
+ unsigned long ofs = je32_to_cpu(pino->offset);
+ unsigned long isize = je32_to_cpu(pino->isize);
+
+ if( size )
+ {
+ memcpy(pDest + ofs, pino->data, size);
+ if( (cur_isize += size) >= isize )
+ {
+ done = 1;
+ break;
+ }
+ }
+ }
+
+ p += (je32_to_cpu(pino->totlen) + 0x03) & ~0x03;
+ }
+ else
+ break;
+ }
+ }
+ }
+
+ pucDst = (unsigned char *) *pulDest;
+ pucEntry = (unsigned char *) *(pulDest + 1);
+ dataLen = (unsigned int) *(pulDest + 2);
+ pucSrc = (unsigned char *) (pulDest + 3);
+
+ ret = decompressLZMA(pucSrc, dataLen, pucDst, 23*1024*1024);
+ if (ret != 0)
+ printf("Failed to decompress image. Corrupted image?\n");
+ else
+ {
+ cfe_loadargs_t la;
+
+ /* Save the rootfs offset of the rootfs that the Linux image
+ * is loaded from at the memory location before the Linux load
+ * address. The Linux image uses this value to determine the
+ * the rootfs to use.
+ */
+ *(unsigned long *) (pucDst - 4) = (start_blk * len) / 1024;
+
+ printf("Decompression OK!\n");
+ la.la_entrypt = (long) pucEntry;
+ printf("Entry at 0x%p\n",la.la_entrypt);
+ cfe_go(&la); // never return...
+ }
+ }
+ else
+ printf("ERROR: A JFFS2 directory entry for %s was not found.\n",fname);
+
+ return( ret );
+}
+
+static int bootNandImage(void)
+{
+ int ret = -1;
+ char *msgA, *msgB;
+ PFILE_TAG pTag1 = getTagFromPartition(1);
+ PFILE_TAG pTag2 = getTagFromPartition(2);
+ int seq1 = (pTag1) ? atoi(pTag1->imageSequence) : -1;
+ int seq2 = (pTag2) ? atoi(pTag2->imageSequence) : -1;
+ int start_blk, end_blk, rootfsA, rootfsB;
+ int len = flash_get_sector_size(0) / 1024;
+ NVRAM_DATA nvramData;
+
+ readNvramData(&nvramData);
+ validateNandPartTbl(&nvramData);
+
+ if( pTag1 && pTag2 )
+ {
+ if( bootInfo.bootPartition == BOOT_LATEST_IMAGE )
+ {
+ msgA = "Booting from latest image (0x%8.8lx) ...\n";
+ msgB = "Booting from previous image (0x%8.8lx) ...\n";
+ rootfsA = (seq2 > seq1) ? NP_ROOTFS_2 : NP_ROOTFS_1;
+ }
+ else /* Boot from the previous image. */
+ {
+ msgA = "Booting from previous image (0x%8.8lx) ...\n";
+ msgB = "Booting from latest image (0x%8.8lx) ...\n";
+ rootfsA = (seq2 <= seq1) ? NP_ROOTFS_2 : NP_ROOTFS_1;
+ }
+
+ rootfsB = (rootfsA == NP_ROOTFS_2) ? NP_ROOTFS_1 : NP_ROOTFS_2;
+ start_blk = nvramData.ulNandPartOfsKb[rootfsA] / len;
+ end_blk = start_blk +
+ (nvramData.ulNandPartSizeKb[rootfsA] / len);
+ printf(msgA, FLASH_BASE + (nvramData.ulNandPartOfsKb[rootfsA] * 1024));
+ if( (ret = bootNandImageFromRootfs(start_blk, end_blk)) != 0 )
+ {
+ start_blk = nvramData.ulNandPartOfsKb[rootfsB] / len;
+ end_blk = start_blk +
+ (nvramData.ulNandPartSizeKb[rootfsB] / len);
+ printf(msgB, FLASH_BASE+(nvramData.ulNandPartOfsKb[rootfsB]*1024));
+ if( (ret = bootNandImageFromRootfs(start_blk, end_blk)) != 0 )
+ printf("Unable to boot image.\n");
+ }
+ }
+ else
+ {
+ if( pTag1 )
+ rootfsA = NP_ROOTFS_1;
+ else
+ if( pTag2 )
+ rootfsA = NP_ROOTFS_2;
+
+ if( pTag1 || pTag2 )
+ {
+ start_blk = nvramData.ulNandPartOfsKb[rootfsA] / len;
+ end_blk = start_blk +
+ (nvramData.ulNandPartSizeKb[rootfsA] / len);
+ printf("Booting from only image (0x%8.8lx) ...\n",
+ FLASH_BASE + (nvramData.ulNandPartOfsKb[rootfsA] * 1024));
+ if( (ret = bootNandImageFromRootfs(start_blk, end_blk)) != 0 )
+ printf("Unable to boot image.\n");
+ }
+ else
+ printf("No image found.\n");
+ }
+
+ return( ret );
+}
+
+static int autoRun(char *imageName)
+{
+ char ipImageName[BOOT_FILENAME_LEN + BOOT_IP_LEN];
+ int ret;
+
+ if (bootInfo.runFrom == 'f' && !imageName)
+ {
+ if (!imageName)
+ {
+ if( flash_get_flash_type() != FLASH_IFC_NAND )
+ {
+ PFILE_TAG pTag = getBootImageTag();
+ int flash_addr_kernel = atoi(pTag->kernelAddress) + BOOT_OFFSET;
+
+ ret = bootCompressedImage((unsigned int *)flash_addr_kernel, TRUE);
+ }
+ else
+ ret = bootNandImage();
+ }
+ else
+ printf("Image name not allowed for boot from flash.\n");
+ }
+ else // loading from host
+ {
+ if (imageName)
+ {
+ if (strchr(imageName, ':'))
+ strcpy(ipImageName, imageName);
+ else
+ {
+ strcpy(ipImageName, bootInfo.hostIp);
+ strcat(ipImageName, ":");
+ strcat(ipImageName, imageName);
+ }
+ }
+ else // use default host file name
+ {
+ strcpy(ipImageName, bootInfo.hostIp);
+ strcat(ipImageName, ":");
+ strcat(ipImageName, bootInfo.hostFileName);
+ }
+
+ // try uncompressed image first
+ ret = bootImage("tftp", "eth0", LOADFLG_EXECUTE | LOADFLG_NOISY, ipImageName);
+
+ if( ret == CFE_ERR_NOTELF )
+ {
+ uint8_t *ptr = (uint8_t *) KERNADDR(FLASH_STAGING_BUFFER);
+ // next try as a compressed image
+ printf("Retry loading it as a compressed image.\n");
+ if ((ret = loadRaw(ipImageName, ptr)) > 0)
+ bootCompressedImage((unsigned int *) ptr, TRUE);
+ }
+ }
+
+ return ret;
+}
+
+
+// run program from compressed image in flash or from tftped program from host
+static int ui_cmd_run_program(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int ret;
+
+ if( getBootImageTag() || bootInfo.runFrom == 'r' )
+ {
+ char *imageName;
+
+ imageName = cmd_getarg(cmd, 0);
+ g_processing_cmd = 1;
+ ret = autoRun(imageName);
+ }
+ else
+ {
+ printf("ERROR: There is not a valid image to boot from.\n");
+ ret = CFE_ERR_FILENOTFOUND;
+ }
+
+ return( ret );
+}
+
+
+static int ui_cmd_print_system_info(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ return printSysInfo();
+}
+
+static int ui_cmd_change_bootline(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ return changeBootLine();
+}
+
+static int ui_cmd_set_afe_id(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ return changeAfeId();
+}
+
+void ui_dumpaddr( unsigned char *pAddr, int nLen );
+void ui_dumpaddr( unsigned char *pAddr, int nLen )
+{
+ static char szHexChars[] = "0123456789abcdef";
+ char szLine[80];
+ char *p = szLine;
+ unsigned char ch, *q;
+ int i = 0, j, size = 0;
+ unsigned long ul;
+ unsigned short us;
+
+ if( ((unsigned long) pAddr & 0xff000000) == 0xff000000 ||
+ ((unsigned long) pAddr & 0xff000000) == 0xb0000000 )
+ {
+ if (nLen == 2) {
+ pAddr = (unsigned char *) ((unsigned long) pAddr & ~0x01);
+ } else if (nLen != 1) {
+ /* keeping the old logic as is. */
+ if( ((unsigned long) pAddr & 0x03) != 0 )
+ nLen += 4;
+ pAddr = (unsigned char *) ((unsigned long) pAddr & ~0x03);
+ }
+ }
+ while( nLen > 0 )
+ {
+ sprintf( szLine, "%8.8lx: ", (unsigned long) pAddr );
+ p = szLine + strlen(szLine);
+
+ if( ((unsigned long) pAddr & 0xff000000) == 0xff000000 ||
+ ((unsigned long) pAddr & 0xff000000) == 0xb0000000 )
+ {
+ for(i = 0; i < 6 && nLen > 0; i += sizeof(long), nLen -= sizeof(long))
+ {
+ if (nLen == 1) {
+ q = pAddr;
+ size = 1;
+ } else if (nLen == 2) {
+ us = *(unsigned short *)pAddr;
+ q = (unsigned char *) &us;
+ size = 2;
+ } else {
+ ul = *(unsigned long *) &pAddr[i];
+ q = (unsigned char *) &ul;
+ size = sizeof(long);
+ }
+ for( j = 0; j < size; j++ )
+ {
+ *p++ = szHexChars[q[j] >> 4];
+ *p++ = szHexChars[q[j] & 0x0f];
+ }
+ *p++ = ' ';
+ }
+ }
+ else
+ {
+ for(i = 0; i < 16 && nLen > 0; i++, nLen-- )
+ {
+ ch = pAddr[i];
+
+ *p++ = szHexChars[ch >> 4];
+ *p++ = szHexChars[ch & 0x0f];
+ *p++ = ' ';
+ }
+ }
+
+ for( j = 0; j < 16 - i; j++ )
+ *p++ = ' ', *p++ = ' ', *p++ = ' ';
+
+ *p++ = ' ', *p++ = ' ', *p++ = ' ';
+
+ for( j = 0; j < i; j++ )
+ {
+ ch = pAddr[j];
+ *p++ = (ch >= ' ' && ch <= '~') ? ch : '.';
+ }
+
+ *p++ = '\0';
+ printf( "%s\r\n", szLine );
+
+ pAddr += i;
+ }
+ printf( "\r\n" );
+} /* ui_dumpaddr */
+
+static int ui_cmd_dump_mem(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *pszAddr = cmd_getarg(cmd, 0);
+ char *pszLen = cmd_getarg(cmd, 1);
+ if( pszAddr && pszLen )
+ ui_dumpaddr((unsigned char *) xtoi(pszAddr), atoi(pszLen));
+ else
+ printf("dm address_in_hex length_in_decimal\n");
+
+ return( 0 );
+}
+
+static int ui_cmd_set_mem(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *pszAddr = cmd_getarg(cmd, 0);
+ char *pszValue = cmd_getarg(cmd, 1);
+ char *pszSize = cmd_getarg(cmd, 2);
+ if( pszAddr && pszValue && pszSize )
+ {
+ unsigned long ulAddr = (unsigned long) xtoi(pszAddr);
+ unsigned long ulValue = (unsigned long) atoi(pszValue);
+ int nSize = atoi(pszSize);
+ unsigned long *pul = (unsigned long *) ulAddr;
+ unsigned short *pus = (unsigned short *) ulAddr;
+ unsigned char *puc = (unsigned char *) ulAddr;
+ switch( nSize )
+ {
+ case 4:
+ *pul = (unsigned long) ulValue;
+ break;
+
+ case 2:
+ *pus = (unsigned short) ulValue;
+ break;
+
+ case 1:
+ *puc = (unsigned char) ulValue;
+ break;
+
+ default:
+ printf("sm address_in_hex value_in_hex size_4_2_or_1");
+ break;
+ }
+
+ ui_dumpaddr((unsigned char *) ulAddr, 4);
+ }
+ else
+ printf("sm address_in_hex value_in_hex size_4_2_or_1");
+
+ return( 0 );
+}
+
+static int ui_cmd_check_mem(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ #define RAM_BASE_ADDRESS 0xa0000000
+ #define BOOT_CODE_SIZE 256 * 1024 // 256KB
+ #define CFE_MEM_SPACE 0xa0400000
+ #define CFE_MEM_SIZE 4*1024*1024 // 4MB
+ #define MEMORY_SIZE 32*1024*1024 // 32MB
+ #define MAGIC_NUMBER 0xacacacac
+
+ #define NAND_SECTOR_SIZE (16*1024) // 16KB
+ #define NAND_TEST_SIZE (30*1024*1024) // 30MB
+
+ unsigned char *addr = NULL;
+ int pass=1;
+
+#if 0
+ unsigned int buf1[NAND_SECTOR_SIZE/4];
+ unsigned int buf2[NAND_SECTOR_SIZE/4];
+ int i, j;
+#endif
+
+ printf("Verifying DRAM access...\n");
+ for(addr=(unsigned char *)(RAM_BASE_ADDRESS+BOOT_CODE_SIZE); addr< (unsigned char *)(RAM_BASE_ADDRESS+MEMORY_SIZE); addr+=4)
+ {
+ if( addr< (unsigned char *)CFE_MEM_SPACE || addr > (unsigned char *)CFE_MEM_SPACE+CFE_MEM_SIZE )
+ {
+ *(unsigned long *)addr = MAGIC_NUMBER;
+ }
+ }
+
+ for(addr=(unsigned char *)(RAM_BASE_ADDRESS+BOOT_CODE_SIZE); addr< (unsigned char *)(RAM_BASE_ADDRESS+MEMORY_SIZE); addr+=4)
+ {
+ if( addr< (unsigned char *)CFE_MEM_SPACE || addr > (unsigned char *)CFE_MEM_SPACE+CFE_MEM_SIZE )
+ {
+ if( *(unsigned long *)addr != MAGIC_NUMBER )
+ pass=0;
+ }
+ }
+ if(pass)
+ printf("DRAM check OK!!!!\n");
+ else
+ printf("DRAM check NG!!!!\n");
+
+#if 0
+ //printf("Verifying NAND flash access...\n");
+ pass=1;
+
+ for(i=0; i<NAND_SECTOR_SIZE/4; i++)
+ {
+ buf1[i]=MAGIC_NUMBER;
+ }
+
+ /* The CFE ROM boot loader saved the rootfs partition index at the
+ * memory location before CFE RAM load address.
+ */
+ extern unsigned char _ftext;
+ int rootfs = (int) *(&_ftext - 1);
+ NVRAM_DATA nvramData;
+ int offset = 0;
+ int blk_start;
+
+ readNvramData(&nvramData);
+
+ if(rootfs == NP_ROOTFS_1 && nvramData.ulNandPartSizeKb[NP_ROOTFS_2]>0)
+ offset = nvramData.ulNandPartOfsKb[NP_ROOTFS_2] * 1024;
+ else
+ offset = nvramData.ulNandPartOfsKb[NP_ROOTFS_1] * 1024;
+
+ printf("Verifying NAND flash access from 0x%08x...\n", FLASH_BASE+offset);
+
+ for(i=0; i<NAND_TEST_SIZE/NAND_SECTOR_SIZE; i++, offset+=NAND_SECTOR_SIZE)
+ {
+ kerSysBcmImageSet(FLASH_BASE+offset, (unsigned char *)buf1, NAND_SECTOR_SIZE, 1);
+ kerSysReadFromFlash( buf2, FLASH_BASE+offset, NAND_SECTOR_SIZE );
+ blk_start = flash_get_blk(FLASH_BASE+offset);
+ flash_sector_erase_int(blk_start); // erase blk before flash
+ if( memcmp(buf1, buf2, NAND_SECTOR_SIZE))
+ {
+ printf("Failed address is 0x%08x\n", FLASH_BASE+offset);
+ for(j=0; j<NAND_SECTOR_SIZE/4; j++)
+ {
+ printf("buf2[%d]=%x\n", j, buf2[j]);
+ }
+ pass=0;
+ break;
+ }
+ }
+
+ if(pass)
+ printf("NAND flash check OK!!!!\n");
+ else
+ printf("NAND flash check NG!!!!\n");
+#endif
+
+ return( 0 );
+}
+
+extern int ui_init_netcmds(void);
+
+int ui_cmd_nmrp(ui_cmdline_t *cmd,int argc,char *argv[]);
+
+int ui_cmd_nmrp(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ _start_nmrp();
+ return 0;
+}
+
+
+int ui_cmd_flash_read(ui_cmdline_t *cmd,int argc,char *argv[]);
+
+int ui_cmd_flash_read(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char str[10];
+
+ kerSysReadFromFlash(str, BOARD_DATA_ADDR, 7);
+
+ printf("%s\n", str);
+
+ return 0;
+}
+
+int ui_cmd_write_boardid(ui_cmdline_t *cmd,int argc,char *argv[]);
+
+int ui_cmd_write_boardid(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+#if (INC_NAND_FLASH_DRIVER==1)
+ NVRAM_DATA nvramData;
+ int len;
+#endif
+
+ if ( argv[0] != NULL ) {
+#if (INC_NAND_FLASH_DRIVER==1)
+ len = strlen(argv[0]);
+ readNvramData(&nvramData);
+ memcpy(nvramData.szFirmwareUpgradeBoardId, argv[0], len);
+ writeNvramData(&nvramData);
+#else
+ kerSysBcmImageSet(BOARD_DATA_ADDR, (unsigned char *)argv[0], strlen(argv[0])+1 , 5);
+#endif
+ }
+#if (INC_NAND_FLASH_DRIVER==1)
+ else {
+ readNvramData(&nvramData);
+ }
+ printf("read board id: %s \n", nvramData.szFirmwareUpgradeBoardId);
+#endif
+ return 0;
+}
+
+/* Foxconn add start by Cliff Wang, 03/23/2010 */
+extern int ui_init_netcmds(void);
+/* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+static int ui_init_bcm63xx_cmds(void)
+{
+ console_name = fakeConsole; // for cfe_rawfs strcmp
+ // Used to flash an image that does not contain a FILE_TAG record.
+
+ /* Foxconn add start by Cliff Wang, 03/23/2010 */
+ cmd_addcmd("flashimage",
+ ui_cmd_flash_router_image,
+ NULL,
+ "Flashes a compressed image after the bootloader.",
+ "eg. flashimage [hostip:]compressed_image_file_name",
+ "");
+ /* Foxconn add end by Cliff Wang, 03/23/2010 */
+ cmd_addcmd("bid",
+ ui_cmd_write_boardid,
+ NULL,
+ "write board id to nand flash.",
+ "eg. bi str ",
+ "");
+
+ cmd_addcmd("reset",
+ ui_cmd_reset,
+ NULL,
+ "Reset the board",
+ "",
+ "");
+
+ cmd_addcmd("b",
+ ui_cmd_set_board_param,
+ NULL,
+ "Change board parameters",
+ "",
+ "");
+
+ cmd_addcmd("a",
+ ui_cmd_set_afe_id,
+ NULL,
+ "Change board AFE ID",
+ "",
+ "");
+
+ cmd_addcmd("i",
+ ui_cmd_erase_psi,
+ NULL,
+ "Erase persistent storage data",
+ "",
+ "");
+
+ if( flash_get_flash_type() != FLASH_IFC_NAND )
+ cmd_addcmd("f",
+ ui_cmd_flash_image,
+ NULL,
+ "Write image to the flash ",
+ "eg. f [[hostip:]filename]<cr> -- if no filename, tftped from host with file name in 'Default host flash file name'",
+ "");
+
+ cmd_addcmd("c",
+ ui_cmd_change_bootline,
+ NULL,
+ "Change booline parameters",
+ "",
+ "");
+
+ cmd_addcmd("p",
+ ui_cmd_print_system_info,
+ NULL,
+ "Print boot line and board parameter info",
+ "",
+ "");
+
+ cmd_addcmd("r",
+ ui_cmd_run_program,
+ NULL,
+ "Run program from flash image or from host depend on [f/h] flag",
+ "eg. r [[hostip:]filenaem]<cr> if no filename, use the file name in 'Default host run file name'",
+ "");
+
+#if (INC_SPI_PROG_NAND==1)
+ cmd_addcmd("n",
+ ui_cmd_erase_nand,
+ NULL,
+ "Erase NAND flash",
+ "e [a]",
+ "");
+#else
+ if( flash_get_flash_type() == FLASH_IFC_NAND )
+ cmd_addcmd("e",
+ ui_cmd_erase_nand,
+ NULL,
+ "Erase NAND flash",
+ "e [a]",
+ "");
+ else
+#endif
+ cmd_addcmd("e",
+ ui_cmd_erase,
+ NULL,
+ "Erase [n]vram or [a]ll flash except bootrom",
+ "e [n/a]",
+ "");
+
+ cmd_addcmd("w",
+ ui_cmd_write_whole_image,
+ NULL,
+ "Write the whole image start from beginning of the flash",
+ "eg. w [hostip:]whole_image_file_name",
+ "");
+
+ cmd_addcmd("chw",
+ ui_cmd_write_chk_image,
+ NULL,
+ "Write chkw image start from beginning of the flash",
+ "eg. chkw [hostip:]whole_image_file_name",
+ "");
+
+ cmd_addcmd("dm",
+ ui_cmd_dump_mem,
+ NULL,
+ "Dump memory or registers.",
+ "eg. dm address_in_hex length_in_decimal",
+ "");
+
+ cmd_addcmd("sm",
+ ui_cmd_set_mem,
+ NULL,
+ "Set memory or registers.",
+ "eg. sm address_in_hex value_in_hex size_4_2_or_1",
+ "");
+
+ cmd_addcmd("nmrp",
+ ui_cmd_nmrp,
+ NULL,
+ "start memory or registers.",
+ "eg. nmrp ",
+ "");
+
+ cmd_addcmd("fr",
+ ui_cmd_flash_read,
+ NULL,
+ "read data from flash.",
+ "eg. fr addr ",
+ "");
+
+ /* Foxconn add start by Cliff Wang, 03/23/2010 */
+ cmd_addcmd("checkmem",
+ ui_cmd_check_mem,
+ NULL,
+ "Check memory.",
+ "Check memory.",
+ "");
+
+ ui_init_tftpdcmds();
+ /* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+ return 0;
+}
+
+
+static int runDelay(int delayCount)
+{
+ int goAuto = 0;
+
+ if (delayCount == 0)
+ return goAuto;
+
+ printf("*** Press any key to stop auto run (%d seconds) ***\n", delayCount);
+ printf("Auto run second count down: %d", delayCount);
+
+ cfe_sleep(CFE_HZ/8); // about 1/4 second
+
+ while (1)
+ {
+ printf("\b%d", delayCount);
+ cfe_sleep(CFE_HZ); // about 1 second
+ if (console_status())
+ break;
+ if (--delayCount == 0)
+ {
+ goAuto = 1;
+ break;
+ }
+ }
+ printf("\b%d\n", delayCount);
+
+ return goAuto;
+}
+
+
+int bcm63xx_run(int breakIntoCfe)
+{
+ int goAuto;
+
+ ui_init_bcm63xx_cmds();
+ printSysInfo();
+ enet_init();
+
+ goAuto = runDelay(bootInfo.bootDelay);
+ if (!breakIntoCfe && runDelay(bootInfo.bootDelay))
+ {
+ /* Foxconn add start by Cliff Wang, 03/23/2010 */
+ if(_start_nmrp() != 0)
+ autoRun(NULL); // never returns
+ /* Foxconn add end by Cliff Wang, 03/23/2010 */
+ }
+ return goAuto;
+}
+
+
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_devs.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_devs.c
new file mode 100755
index 0000000..ac75083
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_devs.c
@@ -0,0 +1,734 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Board device initialization File: bcm94710_devs.c
+ *
+ * This is the "C" part of the board support package. The
+ * routines to create and initialize the console, wire up
+ * device drivers, and do other customization live here.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * XX Copyright 2000,2001
+ * Broadcom Corporation. All rights reserved.
+ *
+ * BROADCOM PROPRIETARY AND CONFIDENTIAL
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the license.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_printf.h"
+
+/* Foxconn add start by Cliff Wang, 03/23/2010 */
+#include "lib_string.h"
+/* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+#include "cfe_timer.h"
+#include "cfe.h"
+#include "bcm_map.h"
+#include "bcm_hwdefs.h"
+#include "bcmTag.h"
+#include "dev_bcm63xx_flash.h"
+#include "bcm63xx_util.h"
+#include "flash_api.h"
+
+/* Foxconn add start by Cliff Wang, 03/23/2010 */
+#include "tftpd.h"
+/* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+static int checkForResetToDefaultHold( unsigned short rstToDfltIrq );
+
+/* Foxconn added start , 1/29/2010 */
+#include "gpio_drv.h"
+#include "foxconnCfg.h"
+
+typedef enum
+{
+ kGpioInactive,
+ kGpioActive
+} GPIO_STATE_t;
+static int test_led_control(int on_off);
+int power_led_toggle(int state);
+int nmrp_led_toggle(void);
+int verify_board_id(char *buf);
+int verify_checksum(char *buf, unsigned long buf_len, unsigned long chksum);
+#define NR_LED 24
+/* Foxconn added end , 1/29/2010 */
+
+/* *********************************************************************
+ * Devices we're importing
+ ********************************************************************* */
+
+extern cfe_driver_t bcm63xx_uart;
+extern cfe_driver_t bcm63xx_enet;
+
+/* *********************************************************************
+ * board_console_init()
+ *
+ * Add the console device and set it to be the primary
+ * console.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void board_console_init(void)
+{
+ /* Add the serial port driver. */
+ cfe_add_device(&bcm63xx_uart,0,0,0);
+
+ cfe_set_console( "uart0" );
+}
+
+
+/* *********************************************************************
+ * board_device_init()
+ *
+ * Initialize and add other devices. Add everything you need
+ * for bootstrap here, like disk drives, flash memory, UARTs,
+ * network controllers, etc.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void board_device_init(void)
+{
+ unsigned short GPIOOverlays;
+
+ kerSysFlashInit();
+
+#if defined (_BCM96328_)
+ if( BpGetGPIOverlays(&GPIOOverlays) == BP_SUCCESS ) {
+ /* Start with all HW LEDs disabled */
+ LED->ledHWDis |= 0xFFFFFF;
+ if (GPIOOverlays & BP_OVERLAY_SERIAL_LEDS) {
+ GPIO->PinMuxSel |= PINMUX_SERIAL_LED_DATA;
+ GPIO->PinMuxSel |= PINMUX_SERIAL_LED_CLK;
+ LED->ledInit |= LED_SERIAL_LED_EN;
+ }
+ /* Enable LED controller to drive GPIO */
+ /* foxconn modified start to let hardware control only act LEDs, Bob, 08/04/2010 */
+ if (GPIOOverlays & BP_OVERLAY_EPHY_LED_0) {
+ GPIO->PinMuxSel |= PINMUX_EPHY0_ACT_LED;
+ //GPIO->GPIOMode |= (1 << EPHY0_SPD_LED);
+ //LED->ledHWDis &= ~(1 << EPHY0_SPD_LED);
+ }
+ if (GPIOOverlays & BP_OVERLAY_EPHY_LED_1) {
+ GPIO->PinMuxSel |= PINMUX_EPHY1_ACT_LED;
+ //GPIO->GPIOMode |= (1 << EPHY1_SPD_LED);
+ //LED->ledHWDis &= ~(1 << EPHY1_SPD_LED);
+ }
+ if (GPIOOverlays & BP_OVERLAY_EPHY_LED_2) {
+ GPIO->PinMuxSel |= PINMUX_EPHY2_ACT_LED;
+ //GPIO->GPIOMode |= (1 << EPHY2_SPD_LED);
+ //LED->ledHWDis &= ~(1 << EPHY2_SPD_LED);
+ }
+ if (GPIOOverlays & BP_OVERLAY_EPHY_LED_3) {
+ GPIO->PinMuxSel |= PINMUX_EPHY3_ACT_LED;
+ //GPIO->GPIOMode |= (1 << EPHY3_SPD_LED);
+ //LED->ledHWDis &= ~(1 << EPHY3_SPD_LED);
+ }
+ /* foxconn modified end, Bob, 08/04/2010 */
+ }
+#endif
+
+#if defined (_BCM96362_)
+ if( BpGetGPIOverlays(&GPIOOverlays) == BP_SUCCESS ) {
+ /* Start with all HW LEDs disabled */
+ LED->ledHWDis |= 0xFFFFFF;
+ if (GPIOOverlays & BP_OVERLAY_SERIAL_LEDS) {
+ GPIO->GPIOMode |= (GPIO_MODE_SERIAL_LED_CLK | GPIO_MODE_SERIAL_LED_DATA);
+ LED->ledInit |= LED_SERIAL_LED_EN;
+ }
+ /* Map HW LEDs to LED controller inputs and enable LED controller to drive GPIO */
+ if (GPIOOverlays & BP_OVERLAY_EPHY_LED_0) {
+ LED->ledLinkActSelHigh |= ((1 << (LED_ENET0 - 4)) << LED_4_LINK_SHIFT);
+ GPIO->LEDCtrl |= (1 << LED_ENET0);
+ LED->ledHWDis &= ~(1 << LED_ENET0);
+ }
+ if (GPIOOverlays & BP_OVERLAY_EPHY_LED_1) {
+ LED->ledLinkActSelHigh |= ((1 << (LED_ENET1 - 4)) << LED_5_LINK_SHIFT);
+ GPIO->LEDCtrl |= (1 << LED_ENET1);
+ LED->ledHWDis &= ~(1 << LED_ENET1);
+ }
+ if (GPIOOverlays & BP_OVERLAY_EPHY_LED_2) {
+ LED->ledLinkActSelHigh |= ((1 << (LED_ENET2 - 4)) << LED_6_LINK_SHIFT);
+ GPIO->LEDCtrl |= (1 << LED_ENET2);
+ LED->ledHWDis &= ~(1 << LED_ENET2);
+ }
+ if (GPIOOverlays & BP_OVERLAY_EPHY_LED_3) {
+ LED->ledLinkActSelHigh |= ((1 << (LED_ENET3 - 4)) << LED_7_LINK_SHIFT);
+ GPIO->LEDCtrl |= (1 << LED_ENET3);
+ LED->ledHWDis &= ~(1 << LED_ENET3);
+ }
+ }
+#endif
+
+#if defined (_BCM96368_)
+ TIMER->WDResetCount = 50000; // Assert reset for 1ms only. If reset asserted for too
+ // long chip reboots twice
+ if( BpGetGPIOverlays(&GPIOOverlays) == BP_SUCCESS ) {
+ if (GPIOOverlays & BP_OVERLAY_EPHY_LED_0) {
+ GPIO->GPIOMode |= GPIO_MODE_EPHY0_LED;
+ GPIO->GPIODir |= GPIO_MODE_EPHY0_LED;
+ }
+
+ if (GPIOOverlays & BP_OVERLAY_EPHY_LED_1) {
+ GPIO->GPIOMode |= GPIO_MODE_EPHY1_LED;
+ GPIO->GPIODir |= GPIO_MODE_EPHY1_LED;
+ }
+
+ if (GPIOOverlays & BP_OVERLAY_EPHY_LED_2) {
+ GPIO->GPIOMode |= GPIO_MODE_EPHY2_LED;
+ GPIO->GPIODir |= GPIO_MODE_EPHY2_LED;
+ }
+
+ if (GPIOOverlays & BP_OVERLAY_EPHY_LED_3) {
+ GPIO->GPIOMode |= GPIO_MODE_EPHY3_LED;
+ GPIO->GPIODir |= GPIO_MODE_EPHY3_LED;
+ }
+
+ if (GPIOOverlays & BP_OVERLAY_SERIAL_LEDS) {
+ GPIO->GPIOMode |= (GPIO_MODE_SERIAL_LED_CLK | GPIO_MODE_SERIAL_LED_DATA);
+ GPIO->GPIODir |= (GPIO_MODE_SERIAL_LED_CLK | GPIO_MODE_SERIAL_LED_DATA);
+ GPIO->SerialLed = 0xffffffff;
+ }
+ }
+
+ /* These blocks will be enabled by the appropriate driver if they are
+ * compiled into a router image.
+ */
+ PERF->blkEnables &= ~(USBH_CLK_EN | PCM_CLK_EN | SAR_CLK_EN | USBD_CLK_EN);
+#endif
+
+#if defined (_BCM96816_)
+ TIMER->WDResetCount = 50000; // Assert reset for 1ms only. If reset asserted for too
+ // long chip reboots twice
+
+ if( BpGetGPIOverlays(&GPIOOverlays) == BP_SUCCESS ) {
+ if (GPIOOverlays & BP_OVERLAY_GPHY_LED_0) {
+ GPIO->GPIOMode |= GPIO_MODE_GPHY0_LED;
+ GPIO->GPIODir |= GPIO_MODE_GPHY0_LED;
+ }
+
+ if (GPIOOverlays & BP_OVERLAY_GPHY_LED_1) {
+ GPIO->GPIOMode |= GPIO_MODE_GPHY1_LED;
+ GPIO->GPIODir |= GPIO_MODE_GPHY1_LED;
+ }
+
+ if (GPIOOverlays & BP_OVERLAY_SERIAL_LEDS) {
+ GPIO->GPIOMode |= (GPIO_MODE_SERIAL_LED_CLK | GPIO_MODE_SERIAL_LED_DATA);
+ GPIO->GPIODir |= (GPIO_MODE_SERIAL_LED_CLK | GPIO_MODE_SERIAL_LED_DATA);
+ GPIO->SerialLed = 0xffffffff;
+ }
+
+ if (GPIOOverlays & BP_OVERLAY_MOCA_LED) {
+ GPIO->GPIOMode |= GPIO_MODE_MOCA_LED;
+ GPIO->GPIODir |= GPIO_MODE_MOCA_LED;
+ }
+ }
+
+ MISC->miscMoCARst &= ~(MISC_MOCA_RST_REF_DIV2RST | MISC_MOCA_RST_REF_FBDIVRST);
+ MISC->miscMoCARst &= ~MISC_MOCA_RST_REF_VCRST;
+ MISC->miscMoCARst &= ~(MISC_MOCA_RST_REF_OUTDIV_RESET_M_MASK | MISC_MOCA_RST_REF_MDIV2RST);
+ MISC->miscMoCACtl |= (7 << MISC_MOCA_CTL_REF_QP_ICTRL_SHIFT);
+ MISC->miscMoCARst &= ~MISC_MOCA_RST_REF_LD_RESET_STRT;
+ PERF->softResetB &= ~(SOFT_RST_MOCA_CPU | SOFT_RST_MOCA_SYS | SOFT_RST_MOCA);
+#endif
+
+#if defined (_BCM96328_) || defined (_BCM96362_)
+ LED->ledInit &= ~LED_FAST_INTV_MASK;
+ LED->ledInit |= (LED_INTERVAL_20MS * 4) << LED_FAST_INTV_SHIFT;
+#else
+ /* Set blink rate for hardware LEDs. */
+ GPIO->LEDCtrl &= ~LED_INTERVAL_SET_MASK;
+ GPIO->LEDCtrl |= LED_INTERVAL_SET_80MS;
+#endif
+
+ /* Add the ethernet driver. */
+ cfe_add_device( &bcm63xx_enet, 0, 0, 0);
+}
+
+
+void setGpio (unsigned short led_gpio, unsigned short led_state)
+{
+#if 0
+ unsigned short gpio_state;
+
+ if (((led_gpio & BP_ACTIVE_LOW) && (led_state == LED_ON)) ||
+ (!(led_gpio & BP_ACTIVE_LOW) && (led_state == LED_OFF)))
+ gpio_state = 0;
+ else
+ gpio_state = 1;
+#endif
+
+ GPIO->GPIODir |= GPIO_NUM_TO_MASK(led_gpio);
+ if( led_state )
+ GPIO->GPIOio |= GPIO_NUM_TO_MASK(led_gpio);
+ else
+ GPIO->GPIOio &= ~GPIO_NUM_TO_MASK(led_gpio);
+}
+
+
+/* *********************************************************************
+ * board_final_init()
+ *
+ * Do any final initialization, such as adding commands to the
+ * user interface.
+ *
+ * If you don't want a user interface, put the startup code here.
+ * This routine is called just before CFE starts its user interface.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void board_final_init(void)
+{
+ unsigned short rstToDfltIrq;
+ int breakIntoCfe = 0;
+
+ /* Foxconn add start by Cliff Wang, 03/23/2010 */
+ int goAuto;
+ /* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+ setAllLedsOff();
+ setPowerOnLedOn();
+ setGpio(GPIO_POWER_RED_LED, GPIO_POWER_RED_LED_ON);
+#if (INC_SPI_PROG_NAND==1)
+ rstToDfltIrq = 1 ;
+ breakIntoCfe = rstToDfltIrq;
+#else
+ if( (bootInfo.runFrom == 'f') && getBootImageTag() == NULL ) {
+ setBreakIntoCfeLed();
+ printf("** Flash image not found. **\n\n");
+ kerSysErasePsi();
+ breakIntoCfe = 1;
+ }
+
+ if( BpGetResetToDefaultExtIntr( &rstToDfltIrq ) == BP_SUCCESS ) {
+ if (checkForResetToDefaultHold( rstToDfltIrq )) {
+ kerSysErasePsi();
+ /* Reset the default bootline if the board IP address has changed. */
+ if (strcmp(bootInfo.boardIp, DEFAULT_BOARD_IP) != 0) {
+ setDefaultBootline();
+ }
+ /* Foxconn modified start pling 09/09/2008 */
+ /* just load default, don't break into console */
+ //breakIntoCfe = 1;
+ printf("\n** Load default! **\n\n");
+ /* Foxconn modified end pling 09/09/2008 */
+ }
+ }
+#endif
+ /* Foxconn add start by Cliff Wang, 03/23/2010 */
+ goAuto = bcm63xx_run(breakIntoCfe);
+ setBreakIntoCfeLed();
+ if(goAuto)
+ {
+ ui_docommand("tftpd");
+ }
+ /* Foxconn add end by Cliff Wang, 03/23/2010 */
+}
+
+/* *********************************************************************
+ * Miscellaneous Board Functions
+ ********************************************************************* */
+
+/* *********************************************************************
+ * checkForResetToDefaultHold()
+ *
+ * Determines if the user is holding the reset to default button.
+ *
+ * Input parameters:
+ * Reset to default irq#
+ *
+ * Return value:
+ * 1 - break into the CFE, 0 - continue boot sequence
+ ********************************************************************* */
+#if (INC_SPI_PROG_NAND==0)
+static int checkForResetToDefaultHold( unsigned short rstToDfltIrq )
+{
+ const int nBreakIntoCfeDelay = 5;
+ int ret = 0;
+ int i;
+ uint32 irqBit;
+ volatile uint32 *extIrqReg;
+
+ extIrqReg = &PERF->ExtIrqCfg;
+ irqBit = 1 << (rstToDfltIrq + EI_STATUS_SHFT);
+
+#if defined(_BCM96368_)
+ if (rstToDfltIrq >= BP_EXT_INTR_4 && rstToDfltIrq <= BP_EXT_INTR_5) {
+ extIrqReg = &PERF->ExtIrqCfg1;
+ irqBit = 1 << (rstToDfltIrq - BP_EXT_INTR_4 + EI_STATUS_SHFT);
+ }
+#endif
+
+ /* Loop while the reset to default button is depressed. */
+ for(i = 0; !(*extIrqReg & irqBit); i++) {
+ if (i == nBreakIntoCfeDelay) {
+ setBreakIntoCfeLed();
+ printf("\n*** Break into CFE console ***\n\n");
+ ret = 1;
+ break;
+ }
+ cfe_sleep(CFE_HZ);
+ }
+
+ return( ret );
+}
+#endif
+/* *********************************************************************
+ * setLed(led_gpio, led_state)
+ *
+ * Turns on an LED.
+ *
+ * Input parameters:
+ * LED purpose
+ * LED State
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void setLed (unsigned short led_gpio, unsigned short led_state)
+{
+ unsigned short gpio_state;
+
+ if (((led_gpio & BP_ACTIVE_LOW) && (led_state == LED_ON)) ||
+ (!(led_gpio & BP_ACTIVE_LOW) && (led_state == LED_OFF)))
+ gpio_state = 0;
+ else
+ gpio_state = 1;
+
+#if defined(_BCM96328_)
+ /* Enable LED controller to drive this GPIO */
+ if (!(led_gpio & BP_GPIO_SERIAL))
+ GPIO->GPIOMode |= GPIO_NUM_TO_MASK(led_gpio);
+#endif
+
+#if defined(_BCM96362_)
+ /* Enable LED controller to drive this GPIO */
+ if (!(led_gpio & BP_GPIO_SERIAL))
+ GPIO->LEDCtrl |= GPIO_NUM_TO_MASK(led_gpio);
+#endif
+
+#if defined(_BCM96328_) || defined(_BCM96362_)
+ LED->ledMode &= ~(LED_MODE_MASK << GPIO_NUM_TO_LED_MODE_SHIFT(led_gpio));
+ if( gpio_state )
+ LED->ledMode |= (LED_MODE_OFF << GPIO_NUM_TO_LED_MODE_SHIFT(led_gpio));
+ else
+ LED->ledMode |= (LED_MODE_ON << GPIO_NUM_TO_LED_MODE_SHIFT(led_gpio));
+
+#else
+ if (led_gpio & BP_GPIO_SERIAL) {
+ while (GPIO->SerialLedCtrl & SER_LED_BUSY);
+ if( gpio_state )
+ GPIO->SerialLed |= GPIO_NUM_TO_MASK(led_gpio);
+ else
+ GPIO->SerialLed &= ~GPIO_NUM_TO_MASK(led_gpio);
+ }
+ else {
+ GPIO->GPIODir |= GPIO_NUM_TO_MASK(led_gpio);
+ if( gpio_state )
+ GPIO->GPIOio |= GPIO_NUM_TO_MASK(led_gpio);
+ else
+ GPIO->GPIOio &= ~GPIO_NUM_TO_MASK(led_gpio);
+ }
+#endif
+}
+
+/* *********************************************************************
+ * setAllLedsOff()
+ *
+ * Turns off all board LEDs on init
+ *
+ * Input parameters:
+ * LED purpose
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void setAllLedsOff(void)
+{
+ unsigned short gpio;
+
+ if( BpGetAdslLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetAdslFailLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetSecAdslLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetSecAdslFailLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetWirelessSesLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetHpnaLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetWanDataLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetWanErrorLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetBootloaderPowerOnLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetBootloaderStopLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetVoipLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetVoip1LedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetVoip2LedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetPotsLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetGponLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetMoCALedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetGponFailLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetMoCAFailLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+}
+
+/* *********************************************************************
+ * setPowerOnLedOn()
+ *
+ * Turns on the Power LED.
+ *
+ * Input parameters:
+ * LED purpose
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void setPowerOnLedOn(void)
+{
+ unsigned short gpio;
+ if( BpGetBootloaderStopLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ if( BpGetBootloaderPowerOnLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_ON );
+}
+
+
+/* *********************************************************************
+ * setBreakIntoCfeLed()
+ *
+ * Turns on the alarm LED.
+ *
+ * Input parameters:
+ * LED purpose
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void setBreakIntoCfeLed(void)
+{
+ unsigned short gpio;
+ if( BpGetBootloaderStopLedGpio( &gpio ) == BP_SUCCESS ) {
+ setLed( gpio, LED_ON );
+ if( BpGetBootloaderPowerOnLedGpio( &gpio ) == BP_SUCCESS )
+ setLed( gpio, LED_OFF );
+ }
+}
+
+/* *********************************************************************
+ * softReset()
+ *
+ * Resets the board.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void softReset(void)
+{
+ printf( "\nResetting board...\n" );
+#if defined (_BCM96816_)
+ /* Work around reset issues */
+ HVG->reg_hvg_cha_misc |= HVG_SOFT_INIT_0;
+ HVG->reg_hvg_chb_misc |= HVG_SOFT_INIT_0;
+#endif
+
+#if defined(_BCM96328_)
+ TIMER->SoftRst |= SOFT_RESET;
+#else
+ PERF->pll_control |= SOFT_RESET; // soft reset mips
+#if defined(_BCM96368_) || defined(_BCM96816_)
+ PERF->pll_control = 0;
+#endif
+#endif
+ while (1);
+}
+
+/* Foxconn added start , 1/29/2010 */
+extern int nmrp_server_detected;
+
+int test_led_control(int on_off)
+{
+ // unsigned short gpio;
+ int tftpd_state = get_tftpd_state();
+
+ if (tftpd_state == TFTPD_STATE_OFF)
+ {
+ setGpio(GPIO_POWER_RED_LED, GPIO_POWER_RED_LED_ON); //turn red power led
+ }
+ else if ( (tftpd_state == TFTPD_STATE_WAIT_IMAGE) || (tftpd_state == TFTPD_STATE_WRITE_IMAGE) )
+ {
+ if (on_off==1)
+ {
+ setGpio(GPIO_POWER_RED_LED, GPIO_POWER_RED_LED_ON);
+ }
+ else
+ {
+ setGpio(GPIO_POWER_RED_LED, GPIO_POWER_RED_LED_OFF);
+ }
+ }
+
+ return 0;
+}
+
+int power_led_toggle(int state)
+{
+ test_led_control(state);
+ return 0;
+}
+
+int nmrp_led_toggle(void)
+{
+ static int led_state = 0;
+
+ /* Foxconn added end for U12H154 */
+
+ if (led_state == 0)
+ {
+ led_state = 1;
+ setGpio(18, 1);
+ }
+ else
+ {
+ led_state = 0;
+ setGpio(18, 0);
+ }
+
+ return 0;
+}
+
+
+static unsigned long calculate_checksum (int action, char *s, int size)
+{
+ static unsigned long c0, c1;
+ unsigned long checksum, b;
+ int i;
+ switch (action)
+ {
+ case 0:
+ c0 = c1 = 0;
+ break;
+
+ case 1:
+ for (i = 0; i < size; i++)
+ {
+ c0 += s[i] & 0xff;
+ c1 += c0;
+ /* check the lan/wan ports status, Foxconn added by EricHuang, 10/24/2006 */
+ if ((i % 90000) == 0)
+ {
+ printf(".");
+// bcm_robo_check_link_status();
+ }
+ }
+ break;
+
+ case 2:
+ b = (c0 & 65535) + ((c0 >> 16) & 65535);
+ c0 = ((b >> 16) + b) & 65535;
+
+ b = (c1 & 65535) + ((c1 >> 16) & 65535);
+ c1 = ((b >> 16) + b) & 65535;
+
+ checksum = ((c1 << 16) | c0);
+
+ return checksum;
+ }
+ return 0;
+}
+
+int verify_checksum(char *buf, unsigned long buf_len, unsigned long chksum)
+{
+ unsigned long cal_chksum = 0;
+
+ xprintf("Loading .");
+ calculate_checksum (0, NULL, 0);
+ calculate_checksum (1, buf, buf_len);
+ cal_chksum = calculate_checksum (2, NULL, 0);
+ printf("\n");
+
+
+ if (cal_chksum != chksum) {
+ xprintf("Image chksum: 0x%08X\n", chksum);
+ xprintf("Calc chksum: 0x%08X\n", cal_chksum);
+ return -1;
+ }
+
+#ifdef _DEBUG
+ //printf("verify_checksum calculate_checksum = 0x%08X\n", cal_chksum);
+ //printf("verify_checksum image_chksum = 0x%08X\n", chksum);
+#endif
+
+ return 0;
+}
+
+int verify_board_id(char *buf)
+{
+ /* char *board_id = ( char *)BOARD_DATA_ADDR; */
+ char board_id[PROJECT_ID_LEN];
+
+ kerSysReadFromFlash(board_id, BOARD_DATA_ADDR, PROJECT_ID_LEN);
+
+ if(nmrp_server_detected==1) // in NMRP mode
+ {
+ if (strncmp(buf, board_id, PROJECT_ID_LEN) != 0)
+ {
+ printf("verify_board_id failed: (%s)\n", buf);
+ return -1;
+ }
+ }
+ else
+ {
+ if (strcmp(buf, board_id) != 0)
+ {
+ /* Foxconn removed start pling 12/10/2008 */
+ /* Don't check board ID in 'tftpd' mode */
+ printf("verify_board_id failed: (%s)\n", buf);
+ //return -1;
+ /* Foxconn removed end pling 12/10/2008 */
+ }
+ }
+ return 0;
+}
+
+/* Foxconn added end , 1/29/2010 */
+
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_env_subr.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_env_subr.c
new file mode 100755
index 0000000..3ce3a28
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_env_subr.c
@@ -0,0 +1,277 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Environment variable subroutines File: env_subr.c
+ *
+ * This module contains routines to muck with environment variables
+ * (manage the list, read/write to nvram, etc.)
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "env_subr.h"
+///#include "nvram_subr.h"
+
+#include "cfe_error.h"
+#include "cfe.h"
+
+/* *********************************************************************
+ * Types
+ ********************************************************************* */
+
+typedef struct cfe_envvar_s {
+ queue_t qb;
+ int flags;
+ char *name;
+ char *value;
+ /* name and value go here */
+} cfe_envvar_t;
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+queue_t env_envvars = {&env_envvars,&env_envvars};
+extern unsigned int cfe_startflags;
+
+/* *********************************************************************
+ * env_findenv(name)
+ *
+ * Locate an environment variable in the in-memory list
+ *
+ * Input parameters:
+ * name - name of env var to find
+ *
+ * Return value:
+ * cfe_envvar_t pointer, or NULL if not found
+ ********************************************************************* */
+
+static cfe_envvar_t *env_findenv(const char *name)
+{
+ queue_t *qb;
+ cfe_envvar_t *env;
+
+ for (qb = env_envvars.q_next; qb != &env_envvars; qb = qb->q_next) {
+ env = (cfe_envvar_t *) qb;
+ if (strcmp(env->name,name) == 0) break;
+ }
+
+ if (qb == &env_envvars) return NULL;
+
+ return (cfe_envvar_t *) qb;
+
+}
+
+/* *********************************************************************
+ * env_enum(idx,name,namelen,val,vallen)
+ *
+ * Enumerate environment variables. This routine locates
+ * the nth environment variable and copies its name and value
+ * to user buffers.
+ *
+ * The namelen and vallen variables must be preinitialized to
+ * the maximum size of the output buffer.
+ *
+ * Input parameters:
+ * idx - variable index to find (starting with zero)
+ * name,namelen - name buffer and length
+ * val,vallen - value buffer and length
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int env_enum(int idx,char *name,int *namelen,char *val,int *vallen)
+{
+ queue_t *qb;
+ cfe_envvar_t *env;
+
+ for (qb = env_envvars.q_next; qb != &env_envvars; qb = qb->q_next) {
+ if (idx == 0) break;
+ idx--;
+ }
+
+ if (qb == &env_envvars) return CFE_ERR_ENVNOTFOUND;
+ env = (cfe_envvar_t *) qb;
+
+ *namelen = xstrncpy(name,env->name,*namelen);
+ *vallen = xstrncpy(val,env->value,*vallen);
+
+ return 0;
+
+}
+
+/* *********************************************************************
+ * env_envtype(name)
+ *
+ * Return the type of the environment variable
+ *
+ * Input parameters:
+ * name - name of environment variable
+ *
+ * Return value:
+ * flags, or <0 if error occured
+ ********************************************************************* */
+int env_envtype(const char *name)
+{
+ cfe_envvar_t *env;
+
+ env = env_findenv(name);
+
+ if (env) {
+ return env->flags;
+ }
+
+ return CFE_ERR_ENVNOTFOUND;
+}
+
+
+
+/* *********************************************************************
+ * env_delenv(name)
+ *
+ * Delete an environment variable
+ *
+ * Input parameters:
+ * name - environment variable to delete
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int env_delenv(const char *name)
+{
+ cfe_envvar_t *env;
+
+ env = env_findenv(name);
+
+ if (!env) return 0;
+
+ if (!(env->flags & ENV_FLG_READONLY)) {
+ q_dequeue((queue_t *) env);
+ KFREE(env);
+ return 0;
+ }
+
+ return CFE_ERR_ENVNOTFOUND;
+}
+
+/* *********************************************************************
+ * env_getenv(name)
+ *
+ * Retrieve the value of an environment variable
+ *
+ * Input parameters:
+ * name - name of environment variable to find
+ *
+ * Return value:
+ * value, or NULL if variable is not found
+ ********************************************************************* */
+
+char *env_getenv(const char *name)
+{
+ cfe_envvar_t *env;
+
+ env = env_findenv(name);
+
+ if (env) {
+ return env->value;
+ }
+
+ return NULL;
+}
+
+
+/* *********************************************************************
+ * env_setenv(name,value,flags)
+ *
+ * Set the value of an environment variable
+ *
+ * Input parameters:
+ * name - name of variable
+ * value - value of variable
+ * flags - flags for variable (ENV_FLG_xxx)
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int env_setenv(const char *name,char *value,int flags)
+{
+ cfe_envvar_t *env;
+ int namelen;
+
+ env = env_findenv(name);
+ if (env) {
+ if (!(flags & ENV_FLG_ADMIN)) {
+ if (env->flags & ENV_FLG_READONLY) return CFE_ERR_ENVREADONLY;
+ }
+ q_dequeue((queue_t *) env);
+ KFREE(env);
+ }
+
+ namelen = strlen(name);
+
+ env = KMALLOC(sizeof(cfe_envvar_t) + namelen + 1 + strlen(value) + 1,0);
+ if (!env) return CFE_ERR_NOMEM;
+
+ env->name = (char *) (env+1);
+ env->value = env->name + namelen + 1;
+ env->flags = (flags & ENV_FLG_MASK);
+
+ strcpy(env->name,name);
+ strcpy(env->value,value);
+
+ q_enqueue(&env_envvars,(queue_t *) env);
+
+ return 0;
+}
+int env_save(void)
+{
+ return 0;
+}
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_httpd.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_httpd.c
new file mode 100755
index 0000000..dcd5b0a
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_httpd.c
@@ -0,0 +1,1031 @@
+/* milli_httpd - pretty small HTTP server
+** A combination of
+** micro_httpd - really small HTTP server
+** and
+** mini_httpd - small HTTP server
+**
+** Copyright 1999,2000 by Jef Poskanzer <jef@acme.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. 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.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+*/
+
+#if (CFG_WEB_SERVER==1)
+
+/** Includes. **/
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_timer.h"
+#include "cfe_error.h"
+#include "cfe.h"
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+
+#include "bsp_config.h"
+
+#include "bcmTag.h"
+#include "bcm63xx_util.h"
+
+
+/** Externs. **/
+
+extern char ul_html[];
+extern char ulinfo_html[];
+extern int ul_html_size;
+extern int ulinfo_html_size;
+
+extern int g_console_abort;
+extern int g_processing_cmd;
+
+/** Defines. **/
+
+#define SERVER_NAME "micro_httpd"
+#define SERVER_URL "http://www.acme.com/software/micro_httpd/"
+#define SERVER_PORT 80
+#define PROTOCOL "HTTP/1.0"
+#define POST_DATA_START (unsigned char *) \
+ BOARD_IMAGE_DOWNLOAD_ADDRESS
+#define SOCKET_CLOSED -100
+#define NUM_SOCKETS 4
+
+/* Return codes from cfe_web_gets. */
+#define WEB_GETS_DONE 1
+#define WEB_GETS_PENDING 2
+#define WEB_GETS_ERROR 3
+
+/* HTTP states. */
+#define HTTP_INITIAL 0
+#define HTTP_READ_FIRST_HDR 1
+#define HTTP_READ_REMAINING_HDRS 2
+#define HTTP_READ_POST_DATA 3
+
+/* HTTP POST status */
+#define UPLOAD_OK '0'
+#define UPLOAD_FAIL_NO_MEM '1'
+#define UPLOAD_FAIL_NO_FILENAME '2'
+#define UPLOAD_FAIL_ILLEGAL_IMAGE '3'
+#define UPLOAD_FAIL_IMAGE_TOOBIG '4'
+#define UPLOAD_FAIL_CORRUPT_IMAGE '5'
+#define UPLOAD_FAIL_FLASH '6'
+#define UPLOAD_FATAL '7'
+#define UPLOAD_PENDING '8'
+#define UPLOAD_TCP_ERROR '9'
+
+/* HTTP upload image formats. */
+#define NO_IMAGE_FORMAT 0
+#define BROADCOM_IMAGE_FORMAT 1
+#define FLASH_IMAGE_FORMAT 2
+
+
+/** Structs. **/
+
+typedef struct
+{
+ int s;
+ int state;
+ int web_buf_idx;
+ int post_content_length;
+ char web_first_buf[128];
+ char web_buf[256];
+} SOCKET_INFO, *PSOCKET_INFO;
+
+typedef struct
+{
+ char *wp_name;
+ char *wp_content_buf;
+ int *wp_content_size;
+ char *wp_mime_type;
+} WEB_PAGE_MAP, *PWEB_PAGE_MAP;
+
+
+/** Globals. **/
+
+static int g_listen_idx = 0;
+static unsigned char *g_image_start = NULL;
+static int g_image_len = 0;
+static int g_image_format = NO_IMAGE_FORMAT;
+static int g_post_data_in_progress = 0;
+static int g_post_data_idx = 0;
+
+static SOCKET_INFO g_socket_info[NUM_SOCKETS];
+
+static WEB_PAGE_MAP g_web_page_map[] =
+ {
+ {"/", ul_html, &ul_html_size, "text/html"},
+ {"/upload.html", ul_html, &ul_html_size, "text/html"},
+ {"/uploadinfo.html", ulinfo_html, &ulinfo_html_size, "text/html"},
+ {NULL, NULL, 0, NULL}
+ };
+
+
+/** Prototypes. **/
+
+int cfe_web_check(void);
+void cfe_web_fg_process(void);
+void cfe_web_poll(void *x);
+static void cfe_web_listen( int *listen_idx_ptr );
+static void cfe_web_bg_process(PSOCKET_INFO si);
+static int cfe_web_gets( char *web_buf, int web_buf_size,
+ int *web_buf_idx_ptr, int s );
+static int read_first_hdr(int s, char *web_buf, int web_buf_size,
+ int *web_buf_idx_ptr, int *close_tcp_ptr);
+static int read_remaining_hdrs(int s, char *web_buf, int web_buf_size,
+ int *web_buf_idx_ptr, int *close_tcp_ptr, int *content_length_ptr);
+static char read_post_data( int s, unsigned char *post_data_start,
+ int content_length, int *post_data_idx_ptr );
+static char parse_post_data( int s, unsigned char *post_data_start,
+ int post_data_length, unsigned char **image_start_ptr, int *image_len_ptr,
+ int *image_format_ptr );
+static void send_error( int s, int status, char* title, char* extra_header,
+ char* text );
+static void send_error( int s, int status, char* title, char* extra_header,
+ char* text );
+static void send_headers( int s, int status, char* title, char* extra_header,
+ char* mime_type );
+static void send_page( int s, char *path, int send_headers_flag,
+ char **substs, int num_substs );
+static int cfe_web_tcp_send( int s, char *buf, int size );
+void * memmove(void * dest,const void *src,size_t count);
+
+
+/***************************************************************************
+ * Function Name: cfe_web_check
+ * Description : Checks if an image has been downloaded through an HTTP POST
+ * request and is ready to be written to flash memory.
+ * Returns : 1 - image is ready to be flashed, 0 - nothing to do
+ ***************************************************************************/
+int cfe_web_check(void)
+{
+ return( (g_image_format != NO_IMAGE_FORMAT) ? 1 : 0 );
+} /* cfe_web_check */
+
+
+/***************************************************************************
+ * Function Name: cfe_web_process
+ * Description : Calls the appropriate functions to write an image to
+ * flash memory.
+ * Returns : None.
+ ***************************************************************************/
+void cfe_web_fg_process(void)
+{
+ /* Wait so the uploadinfo web page can be displayed on the browser. */
+ cfe_sleep(CFE_HZ * 2);
+ if( g_image_format == BROADCOM_IMAGE_FORMAT )
+ flashImage( g_image_start );
+ else
+ if( g_image_format == FLASH_IMAGE_FORMAT )
+ writeWholeImage( g_image_start, g_image_len );
+
+ if( g_image_format != NO_IMAGE_FORMAT )
+ softReset();
+
+} /* cfe_web_process */
+
+
+/***************************************************************************
+ * Function Name: cfe_web_poll
+ * Description : The entry point function that is called in the background
+ * at polled intervals. It listens for and processes HTTP
+ * requests.
+ * Returns : None.
+ ***************************************************************************/
+void cfe_web_poll(void *x)
+{
+ static int first_time = 1;
+ static int in_cfe_web_poll = 0;
+
+ PSOCKET_INFO si;
+ int i;
+
+ if( in_cfe_web_poll == 0 )
+ {
+ in_cfe_web_poll = 1;
+
+ /* If this is the first time that this function was called, initialize
+ * the socket info data array.
+ */
+ if( first_time == 1 )
+ {
+ first_time = 0;
+ for( i = 0, si = g_socket_info; i < NUM_SOCKETS; i++, si++ )
+ {
+ si->s = SOCKET_CLOSED;
+ si->state = HTTP_READ_FIRST_HDR;
+ si->web_buf_idx = 0;
+ si->post_content_length = 0;
+ }
+ }
+
+ /* Check the connection state of each socket. */
+ for( i = 0, si = g_socket_info; i < NUM_SOCKETS; i++, si++ )
+ {
+ cfe_web_listen( &g_listen_idx );
+ if( si->s >= 0 )
+ {
+ unsigned int connflag;
+ tcp_status( si->s, &connflag, NULL, NULL );
+ if( connflag == TCPSTATUS_CONNECTED )
+ {
+ cfe_web_bg_process( si );
+ POLL();
+ }
+ else
+ if( connflag == TCPSTATUS_NOTCONN )
+ {
+ console_log("web warning: Unexpected TCP disconnect.");
+ tcp_close(si->s);
+ si->s = SOCKET_CLOSED;
+ si->state = HTTP_READ_FIRST_HDR;
+ si->web_buf_idx = 0;
+ }
+ }
+ }
+
+ in_cfe_web_poll = 0;
+ }
+} /* cfe_web_poll */
+
+
+/***************************************************************************
+ * Function Name: cfe_web_listen
+ * Description : This function checks to see if TCP listen can be issued
+ * on the HTTP port and issues the listen if it can.
+ * Returns : None.
+ ***************************************************************************/
+static void cfe_web_listen( int *listen_idx_ptr )
+{
+ static int port = SERVER_PORT;
+
+ int listen_idx = *listen_idx_ptr;
+ PSOCKET_INFO si = &g_socket_info[listen_idx];
+
+ /* If a TCP socket has been opened, check its connection status. */
+ if( si->s >= 0 )
+ {
+ unsigned int connflag;
+ tcp_status( si->s, &connflag, NULL, NULL );
+
+ /* If the socket is connection, set the next socket index to listen for
+ * a TCP connection.
+ */
+ if( connflag == TCPSTATUS_CONNECTED )
+ {
+ listen_idx = (listen_idx + 1) % NUM_SOCKETS;
+ si = &g_socket_info[listen_idx];
+ }
+ }
+
+ /* If the TCP socket has not been opened, open it and listen for a TCP
+ * connection.
+ */
+ if( si->s == SOCKET_CLOSED )
+ {
+ /* Open the socket in non-blocking mode. */
+ POLL();
+ if( (si->s = tcp_socket()) >= 0 )
+ {
+ console_log("web info: Waiting for connection on socket %d.", si->s);
+ if( tcp_listen(si->s, port) != 0 )
+ console_log("web error: listen error on %d.", si->s);
+ }
+ else
+ {
+ console_log("web error %d: Could not create TCP socket.", si->s);
+ si->s = SOCKET_CLOSED;
+ }
+ }
+
+ *listen_idx_ptr = listen_idx;
+} /* cfe_web_listen */
+
+
+/***************************************************************************
+ * Function Name: cfe_web_bg_process
+ * Description : This function processes an HTTP request on a socket.
+ * Returns : None.
+ ***************************************************************************/
+static void cfe_web_bg_process(PSOCKET_INFO si)
+{
+ char post_subst[] = {UPLOAD_FATAL, '\0'};
+ char *post_substs[] = {post_subst};
+ int close_tcp = 0;
+
+ switch( si->state )
+ {
+ case HTTP_READ_FIRST_HDR:
+ if( read_first_hdr( si->s, si->web_first_buf,
+ sizeof(si->web_first_buf), &si->web_buf_idx, &close_tcp ) == 0 )
+ {
+ /* Not all of the first header has been read yet. Try again later.*/
+ break;
+ }
+
+ /* The first header has been read. */
+ si->state = HTTP_READ_REMAINING_HDRS;
+
+ /* fall thru */
+
+ case HTTP_READ_REMAINING_HDRS:
+ if( read_remaining_hdrs( si->s, si->web_buf, sizeof(si->web_buf),
+ &si->web_buf_idx, &close_tcp, &si->post_content_length ) )
+ {
+ if( g_processing_cmd == 0 )
+ {
+ char *method = NULL;
+ char *path = NULL;
+ char *ptr = (char *) si->web_first_buf;
+
+ method = gettoken(&ptr);
+ if( method )
+ path = gettoken(&ptr);
+
+ /* Process the HTTP request. Only GET and POST are supported. */
+ if( method && path )
+ {
+ if( !strcmpi( method, "get" ) )
+ {
+ send_page( si->s, path, 1, NULL, 0 );
+ close_tcp = 1;
+ }
+ else
+ {
+ if( !strcmpi( method, "post" ) )
+ {
+ if( g_post_data_in_progress == 0 )
+ {
+ g_post_data_in_progress = 1;
+ si->state = HTTP_READ_POST_DATA;
+ }
+ else
+ {
+ send_error( si->s, 501, "Upload Busy",
+ (char*) 0,
+ "An image is already being uploaded." );
+ close_tcp = 1;
+ }
+ }
+ else
+ {
+ send_error( si->s, 501, "Not Implemented",
+ (char*) 0,
+ "That method is not implemented." );
+ close_tcp = 1;
+ }
+ }
+ }
+ else
+ {
+ send_error( si->s, 400, "Bad Request", (char *) 0,
+ "Can't parse request." );
+ close_tcp = 1;
+ }
+ }
+ else
+ {
+ /* A download and flash image command is being executed from
+ * the serial port console.
+ */
+ send_error( si->s, 400, "Bad Request", (char *) 0,
+ "Console command is in progress." );
+ close_tcp = 1;
+ }
+ }
+
+ if( si->state != HTTP_READ_POST_DATA )
+ break;
+
+ case HTTP_READ_POST_DATA:
+ /* Read the post data, which contains an image to flash, into low
+ * memory.
+ */
+ if( (post_subst[0] = read_post_data( si->s, POST_DATA_START,
+ si->post_content_length, &g_post_data_idx )) == UPLOAD_OK )
+ {
+ /* Verify that the post data is a valid image to flash. */
+ post_subst[0] = parse_post_data( si->s, POST_DATA_START,
+ g_post_data_idx, (unsigned char **) &g_image_start, &g_image_len,
+ &g_image_format );
+ }
+
+ switch( post_subst[0] )
+ {
+ case UPLOAD_PENDING:
+ break;
+
+ case UPLOAD_TCP_ERROR:
+ close_tcp = 1;
+ g_post_data_in_progress = 0;
+ g_post_data_idx = 0;
+ break;
+
+ case UPLOAD_OK:
+ /* Notify foreground to abort the console input so it can
+ * write the image to flash memory.
+ */
+ g_console_abort = 1;
+
+ send_page(si->s, "/uploadinfo.html", 0, post_substs, 1);
+ close_tcp = 1;
+ g_post_data_idx = 0;
+ break;
+
+ default:
+ /* The image was downloaded OK but there was a problem with it
+ * so it could not be written to flash memory.
+ */
+ send_page(si->s, "/uploadinfo.html", 0, post_substs, 1);
+ close_tcp = 1;
+ g_post_data_in_progress = 0;
+ g_post_data_idx = 0;
+ break;
+ }
+ break;
+ }
+
+ /* Close the socket if the HTTP transaction is done. */
+ if( close_tcp )
+ {
+ POLL();
+ tcp_close(si->s);
+ si->s = SOCKET_CLOSED;
+ si->state = HTTP_READ_FIRST_HDR;
+ si->web_buf_idx = 0;
+ si->post_content_length = 0;
+ }
+} /* cfe_web_poll */
+
+
+/***************************************************************************
+ * Function Name: cfe_web_gets
+ * Description : Reads from a socket up to a <CR><LF> or <LF>. The socket
+ * is non-blocking.
+ * Returns : WEB_GETS_DONE - Complete line was read.
+ * WEB_GETS_PENDING - Line partially read.
+ * WEB_GETS_ERROR - Socket error.
+ ***************************************************************************/
+static int cfe_web_gets( char *web_buf, int web_buf_size,
+ int *web_buf_idx_ptr, int s )
+{
+ int ret = WEB_GETS_PENDING;
+ unsigned char ch;
+ int web_buf_idx = *web_buf_idx_ptr;
+ char *p = web_buf + web_buf_idx;
+ int continue_reading = 1;
+
+ while( web_buf_idx < web_buf_size && continue_reading )
+ {
+ switch( tcp_recv( s, &ch, 1 ) )
+ {
+ case 0: /* no characters are available to receive */
+ continue_reading = 0;
+ break;
+
+ case 1: /* character was read */
+ if( ch == '\n' )
+ {
+ *p = '\0';
+ continue_reading = 0;
+ ret = WEB_GETS_DONE;
+ }
+ else
+ if( ch != '\r' )
+ {
+ *p++ = ch;
+ web_buf_idx++;
+ }
+ break;
+
+ default:
+ continue_reading = 0;
+ ret = WEB_GETS_ERROR;
+ break;
+ }
+ }
+
+ if( web_buf_idx == web_buf_size )
+ {
+ web_buf[web_buf_idx - 1] = '\0';
+ ret = WEB_GETS_DONE;
+ }
+
+ *web_buf_idx_ptr = web_buf_idx;
+
+ return( ret );
+} /* cfe_web_gets */
+
+
+/***************************************************************************
+ * Function Name: read_first_hdr
+ * Description : This function reads the first HTTP header which contains
+ * the method (GET, POST), path and protocol. For example,
+ * GET /upload.html HTTP/1.1
+ * Returns : 1 - First header was read, 0 - was not read.
+ ***************************************************************************/
+static int read_first_hdr(int s, char *web_buf, int web_buf_size,
+ int *web_buf_idx_ptr, int *close_tcp_ptr)
+{
+ int ret = 0;
+ int sts = cfe_web_gets( web_buf, web_buf_size, web_buf_idx_ptr, s );
+
+ switch( sts )
+ {
+ case WEB_GETS_DONE:
+ /* The first HTTP header has been read into web_buf. */
+ *web_buf_idx_ptr = 0;
+ ret = 1;
+ break;
+
+ case WEB_GETS_ERROR:
+ console_log("web error: TCP read error.");
+ *close_tcp_ptr = 1;
+ break;
+ }
+
+ return( ret );
+} /* read_first_hdr */
+
+
+/***************************************************************************
+ * Function Name: read_remaining_hdrs
+ * Description : This function reads the remaining HTTP headers.
+ * Returns : 1 - Remaining headers were read, 0 - were not read.
+ ***************************************************************************/
+static int read_remaining_hdrs(int s, char *web_buf, int web_buf_size,
+ int *web_buf_idx_ptr, int *close_tcp_ptr, int *content_length_ptr)
+{
+ int ret = 0;
+ int sts = WEB_GETS_DONE;
+
+ while( sts == WEB_GETS_DONE )
+ {
+ sts = cfe_web_gets( web_buf, web_buf_size, web_buf_idx_ptr, s );
+ switch( sts )
+ {
+ case WEB_GETS_DONE:
+ if( *web_buf_idx_ptr == 0 )
+ {
+ /* The remaining HTTP headers have been read. */
+ ret = 1;
+ sts = WEB_GETS_PENDING;
+ }
+ else
+ {
+ char *p2 = web_buf;
+ char *p1 = gettoken(&p2);
+ if( !strcmpi( p1, "Content-Length:" ) )
+ *content_length_ptr=atoi(p2);
+ *web_buf_idx_ptr = 0;
+ }
+ break;
+
+ case WEB_GETS_ERROR:
+ console_log("web error: TCP read error.");
+ *close_tcp_ptr = 1;
+ break;
+ }
+ }
+
+ return( ret );
+} /* read_remaining_hdrs */
+
+
+/***************************************************************************
+ * Function Name: read_post_data
+ * Description : This function reads HTTP POST data which is the contents of
+ * a new image to write to flash memory.
+ * Returns : UPLOAD_OK - all data read
+ * UPLOAD_PENDING - not all data read
+ * UPLOAD_TCP_ERROR - TCP error
+ ***************************************************************************/
+static char read_post_data( int s, unsigned char *post_data_start,
+ int content_length, int *post_data_idx_ptr )
+{
+ char ret = UPLOAD_PENDING;
+ int post_data_idx = *post_data_idx_ptr;
+ int len;
+
+ do
+ {
+ len = tcp_recv( s, (unsigned char*)(post_data_start + post_data_idx),
+ content_length - post_data_idx );
+ post_data_idx += len;
+ POLL();
+ cfe_web_listen( &g_listen_idx );
+ } while( len > 0 && post_data_idx < content_length );
+
+ *post_data_idx_ptr = post_data_idx;
+
+ if( len < 0 )
+ {
+ console_log("web error: TCP read error receiving post data.");
+ ret = UPLOAD_TCP_ERROR;
+ }
+ else
+ if( post_data_idx == content_length )
+ ret = UPLOAD_OK;
+
+ return( ret );
+} /* read_post_data */
+
+
+/***************************************************************************
+ * Function Name: parse_post_data
+ * Description : This function parses HTTP POST data which is the contents of
+ * a new image to write to flash memory.
+ * Returns : UPLOAD_OK or UPLOAD_xxx error
+ ***************************************************************************/
+static char parse_post_data( int s, unsigned char *post_data_start,
+ int post_data_length, unsigned char **image_start_ptr, int *image_len_ptr,
+ int *image_format_ptr )
+{
+ char ret = UPLOAD_OK;
+ unsigned char *p = post_data_start;
+ int boundary_size = 0;
+
+ /* Convert the start boundary field into a string. It will be compared
+ * against the end boundary field below.
+ */
+ while( *p != '\r' && *p != '\n' &&
+ ((int) p - (int) post_data_start) < post_data_length )
+ {
+ p++;
+ }
+
+ if( *p == '\r' || *p == '\n' )
+ {
+ *p++ = '\0';
+ boundary_size = strlen((char*)post_data_start);
+ }
+ else
+ {
+ console_log("web error: HTTP POST start bound field not found.");
+ ret = UPLOAD_FATAL;
+ }
+
+ /* Verify that a filename has been entered. */
+ if( ret == UPLOAD_OK )
+ {
+ unsigned char *fname = NULL;
+ while( memcmp( p, "\r\n\r\n", strlen("\r\n\r\n") ) )
+ {
+ if( *p == 'f' && !memcmp( p, "filename=", strlen("filename=" ) ) )
+ {
+ p += strlen("filename=");
+ fname = p + 1;
+ if( p[0] == '"' && p[1] != '"' )
+ {
+ p++;
+ while( *p != '"' && *p != '\r' && *p != '\n' )
+ p++;
+ *p = '\0';
+ }
+ else
+ {
+ console_log("web error: HTTP POST filename not specified.");
+ ret = UPLOAD_FAIL_NO_FILENAME;
+ }
+ break;
+ }
+
+ p++;
+ }
+
+ if( fname == NULL )
+ {
+ console_log("web error: HTTP POST filename field not found.");
+ ret = UPLOAD_FATAL;
+ }
+ }
+
+ /* Find the start of the image which starts after two consecutive
+ * carriage return, linefeed pairs.
+ */
+ if( ret == UPLOAD_OK )
+ {
+ while( memcmp( p, "\r\n\r\n", strlen("\r\n\r\n") ) )
+ p++;
+
+ p += strlen("\r\n\r\n");
+ if( p[0] != '\r' || p[1] != '\n' ||
+ memcmp(p + 2, post_data_start, boundary_size ) )
+ {
+ *image_start_ptr = p;
+ }
+ else
+ {
+ console_log("web error: HTTP POST no image data.");
+ ret = UPLOAD_FAIL_ILLEGAL_IMAGE;
+ }
+ }
+
+ /* Find the end of the image which contains the same boundary field as
+ * at the start of the buffer.
+ */
+ if( ret == UPLOAD_OK )
+ {
+ p = post_data_start + post_data_length - 1;
+ while( *p == '\r' || *p == '\n' || *p == '-' )
+ p--;
+ p[1] = '\0';
+ p -= boundary_size + 1;
+ if( !memcmp( p + strlen("\r\n"), post_data_start, boundary_size ) )
+ *image_len_ptr = (int) p - (int) *image_start_ptr;
+ else
+ {
+ console_log("web error: HTTP POST end bound field not found.");
+ ret = UPLOAD_FATAL;
+ }
+ }
+
+ /* Verify that the image is (or should be) a Broadcom flash format file or
+ * a flash image format.
+ */
+ if( ret == UPLOAD_OK )
+ {
+ /* Align the image on a 16 byte boundary */
+ if( ((unsigned long) *image_start_ptr & 0x0f) != 0 )
+ {
+ unsigned char *dest = (unsigned char *)
+ ((unsigned long) *image_start_ptr & ~0x0f);
+ unsigned char *src = *image_start_ptr;
+ memmove( dest, src, *image_len_ptr );
+ *image_start_ptr = dest;
+ }
+
+ /* Check if the first part of the image is the Broadcom defined TAG
+ * record.
+ */
+ if( verifyTag( (FILE_TAG *) *image_start_ptr, 0 ) == -1 )
+ {
+ /* It is not a Broadcom flash format file. Now check if it is a
+ * flash image format file. A flash image format file must have a
+ * CRC at the end of the image.
+ */
+ unsigned char *image_ptr = *image_start_ptr;
+ unsigned long image_len = (unsigned long) *image_len_ptr - TOKEN_LEN;
+ unsigned long crc = CRC32_INIT_VALUE;
+
+ crc = getCrc32(image_ptr, image_len, crc);
+ if (memcmp(&crc, image_ptr + image_len, CRC_LEN) == 0)
+ {
+ console_log("web info: Upload %lu bytes, flash image format.",
+ *image_len_ptr);
+ *image_format_ptr = FLASH_IMAGE_FORMAT;
+ }
+ else
+ {
+ console_log("web info: Upload %lu bytes, invalid image format.",
+ *image_len_ptr);
+ ret = UPLOAD_FAIL_ILLEGAL_IMAGE;
+ }
+ }
+ else
+ {
+ console_log("web info: Upload %lu bytes, Broadcom image format.",
+ *image_len_ptr);
+ *image_format_ptr = BROADCOM_IMAGE_FORMAT;
+ }
+ }
+
+ return( ret );
+} /* parse_post_data */
+
+
+/***************************************************************************
+ * Function Name: send_error
+ * Description : This function sends an HTTP error response to the browser.
+ * Returns : None.
+ ***************************************************************************/
+static void send_error( int s, int status, char* title, char* extra_header,
+ char* text )
+{
+ int tcpret = 0;
+ char buf[128];
+ send_headers( s, status, title, extra_header, "text/html" );
+ sprintf( (char *) buf, "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n"
+ "<BODY BGCOLOR=\"#cc9999\"><H4>%d %s</H4>\n", status, title, status,
+ title );
+ tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) );
+ sprintf( (char *) buf, "%s\n", text );
+ tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) );
+ sprintf( (char *) buf, "<HR>\n<ADDRESS><A HREF=\"%s\">%s</A></ADDRESS>\n"
+ "</BODY></HTML>\n", SERVER_URL, SERVER_NAME );
+ tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) );
+
+ if( tcpret < 0 )
+ console_log("web error: TCP write error sending error response.");
+} /* send_error */
+
+
+/***************************************************************************
+ * Function Name: send_headers
+ * Description : This function sends an HTTP response to the browser.
+ * Returns : None.
+ ***************************************************************************/
+static void send_headers( int s, int status, char* title, char* extra_header,
+ char* mime_type )
+{
+ int tcpret = 0;
+ char buf[128];
+ unsigned long secs = (unsigned long) cfe_ticks / CFE_HZ;
+
+ sprintf( buf, "%s %d %s\r\n", PROTOCOL, status, title );
+ tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) );
+ sprintf( buf, "Server: %s\r\n", SERVER_NAME );
+ tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) );
+ sprintf( buf, "Date: Thu, 01 Jan 1970 %2.2d:%2.2d:%2.2d GMT\r\n",
+ secs / 3600, (secs % 3600) / 60, secs % 60 );
+ tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) );
+ if ( extra_header != (char*) 0 )
+ {
+ sprintf( buf, "%s\r\n", extra_header );
+ tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) );
+ }
+ if ( mime_type != (char*) 0 )
+ {
+ sprintf( buf, "Content-Type: %s\r\n", mime_type );
+ tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) );
+ }
+ sprintf( buf, "Connection: close\r\n\r\n" );
+ tcpret = tcp_send( s, (unsigned char*)buf, strlen(buf) );
+
+ if( tcpret < 0 )
+ console_log("web error: TCP write error sending header.");
+} /* send_headers */
+
+
+/***************************************************************************
+ * Function Name: send_page
+ * Description : This function sends a web page to the browser.
+ * Returns : None.
+ ***************************************************************************/
+static void send_page( int s, char *path, int send_headers_flag,
+ char **substs, int num_substs )
+{
+ PWEB_PAGE_MAP map;
+
+ /* Find the specified web page. */
+ for( map = g_web_page_map; map->wp_name; map++ )
+ {
+ if( !strcmp( map->wp_name, path ) )
+ {
+ /* Found the web page. */
+ char *p2 = NULL;
+ char *p = (char *) map->wp_content_buf;
+ int size = *map->wp_content_size;
+ int i = 0;
+
+ if( send_headers_flag )
+ send_headers( s, 200, "Ok", (char *) 0, map->wp_mime_type );
+
+ /* Make substitutions. */
+ while( i < num_substs && (p2 = strnchr( p, '<', size )) != NULL )
+ {
+ if( p2[1] == '%' )
+ {
+ /* Found a substituion pattern. Send up to that point. */
+ if( cfe_web_tcp_send( s, p, (int) (p2 - p) ) < 0 )
+ break;
+
+ /* Send substitution value. */
+ if( cfe_web_tcp_send( s, substs[i], strlen(substs[i]) ) < 0 )
+ break;
+
+ i++;
+
+ /* Skip to end of substitution pattern. */
+ p = p2 + 2; /* skip '<%' */
+ while( p[0] != '%' || p[1] != '>' )
+ p++;
+ p += 2; /* skip '%.' */
+ }
+ else
+ {
+ /* Was not a substitution pattern. Send up that point. */
+ p2++;
+ if( cfe_web_tcp_send( s, p, (int) (p2 - p) ) < 0 )
+ break;
+
+ p = p2;
+ }
+
+ size = *map->wp_content_size - ((int)p-(int)map->wp_content_buf);
+ }
+
+ /* Send remaining part of web page after the last substitution. */
+ cfe_web_tcp_send( s, p, size );
+
+ break; /* for loop */
+ }
+ }
+
+ if( map->wp_name == NULL )
+ send_error( s, 404, "Not Found", (char*) 0, "File not found." );
+} /* send_page */
+
+
+/***************************************************************************
+ * Function Name: cfe_web_tcp_send
+ * Description : Sends data on a TCP non blocking connection and waits for
+ * it to finish.
+ * Returns : > 0 - bytes send, < 0 - TCP error
+ ***************************************************************************/
+static int cfe_web_tcp_send( int s, char *buf, int size )
+{
+ int i, len = 0;
+
+ for( i = 0; i < size; i += len )
+ {
+ POLL();
+ cfe_web_listen( &g_listen_idx );
+ len = tcp_send( s, (unsigned char*)(buf + i), size - i );
+ if( len < 0 )
+ {
+ console_log("web error: TCP write error sending a web page.");
+ break;
+ }
+ }
+
+ return( len );
+} /* cfe_web_tcp_send */
+
+
+/**
+ * memmove - Copy one area of memory to another
+ * @dest: Where to copy to
+ * @src: Where to copy from
+ * @count: The size of the area.
+ *
+ * Unlike memcpy(), memmove() copes with overlapping areas.
+ */
+void * memmove(void * dest,const void *src,size_t count)
+{
+ char *tmp, *s;
+
+ if (dest <= src) {
+ tmp = (char *) dest;
+ s = (char *) src;
+ while (count--)
+ *tmp++ = *s++;
+ }
+ else {
+ tmp = (char *) dest + count;
+ s = (char *) src + count;
+ while (count--)
+ *--tmp = *--s;
+ }
+
+ return dest;
+}
+
+#else
+
+/***************************************************************************
+ * Function Name: Functions stubs.
+ * Description : Used when the web server is not compiled into the CFE.
+ * Returns : None.
+ ***************************************************************************/
+
+int cfe_web_check(void);
+void cfe_web_fg_process(void);
+void cfe_web_poll(void *x);
+
+int cfe_web_check(void)
+{
+ return(0);
+}
+
+void cfe_web_fg_process(void)
+{
+}
+
+void cfe_web_poll(void *x)
+{
+}
+
+#endif
+
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_elf.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_elf.c
new file mode 100755
index 0000000..fb3f122
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_elf.c
@@ -0,0 +1,388 @@
+
+//********** for boot -elf thing from cfe_ldr_elf.c
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * ELF Program Loader File: cfe_ldr_elf.c
+ *
+ * This program parses ELF executables and loads them into memory.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_error.h"
+#include "cfe_devfuncs.h"
+#include "cfe_timer.h"
+#include "cfe_mem.h"
+
+#include "cfe.h"
+#include "cfe_loader.h"
+#include "cfe_fileops.h"
+#include "elf.h"
+
+#include "cfe_boot.h"
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+int bcm63xx_cfe_elfload(cfe_loadargs_t *la);
+
+const cfe_loader_t elfloader = {
+ "elf",
+ bcm63xx_cfe_elfload,
+ 0};
+
+/* *********************************************************************
+ * readprogsegment(fsctx,ref,addr,size)
+ *
+ * Read a program segment, generally corresponding to one
+ * section of the file.
+ *
+ * Input parameters:
+ * fsctx - file I/O dispatch
+ * ref - reference data for open file handle
+ * addr - target virtual address
+ * size - size of region to read
+ *
+ * Return value:
+ * Number of bytes copied or <0 if error occured
+ ********************************************************************* */
+
+static int readprogsegment(fileio_ctx_t *fsctx,void *ref,
+ void *addr,int size,int flags)
+{
+ int res;
+
+#ifdef __long64
+ if (flags & LOADFLG_NOISY) xprintf("0x%016llx/%d ",addr,size);
+#else
+ if (flags & LOADFLG_NOISY) xprintf("0x%x/%d ",addr,size);
+#endif
+
+ res = fs_read(fsctx,ref,addr,size);
+
+ if (res < 0) return CFE_ERR_IOERR;
+ if (res != size) return CFE_ERR_BADELFFMT;
+
+ return size;
+}
+
+
+/* *********************************************************************
+ * readclearbss(addr,size)
+ *
+ * Process a BSS section, zeroing memory corresponding to
+ * the BSS.
+ *
+ * Input parameters:
+ * addr - address to zero
+ * size - length of area to zero
+ *
+ * Return value:
+ * number of zeroed bytes or <0 if error occured
+ ********************************************************************* */
+
+static int readclearbss(void *addr,int size,int flags)
+{
+
+#ifdef __long64
+ if (flags & LOADFLG_NOISY) xprintf("0x%016llx/%d ",addr,size);
+#else
+ if (flags & LOADFLG_NOISY) xprintf("0x%x/%d ",addr,size);
+#endif
+
+ if (size > 0) memset(addr,0,size);
+ return size;
+}
+
+
+/* *********************************************************************
+ * elfgetshdr(ops,ref,ep)
+ *
+ * Get a section header from the ELF file
+ *
+ * Input parameters:
+ * ops - file I/O dispatch
+ * ref - reference data for open file
+ * ep - extended header info
+ *
+ * Return value:
+ * copy of section header (malloc'd) or NULL if no memory
+ ********************************************************************* */
+
+static Elf32_Shdr *elfgetshdr(fileio_ctx_t *fsctx,void *ref,Elf32_Ehdr *ep)
+{
+ Elf32_Shdr *shtab;
+ unsigned size = ep->e_shnum * sizeof(Elf32_Shdr);
+
+ shtab = (Elf32_Shdr *) KMALLOC(size,0);
+ if (!shtab) {
+ return NULL;
+ }
+
+ if (fs_seek(fsctx,ref,ep->e_shoff,FILE_SEEK_BEGINNING) != ep->e_shoff ||
+ fs_read(fsctx,ref,(uint8_t *)shtab,size) != size) {
+ KFREE(shtab);
+ return NULL;
+ }
+
+ return (shtab);
+}
+
+/* *********************************************************************
+ * elfload_internal(ops,ref,entrypt,flags)
+ *
+ * Read an ELF file (main routine)
+ *
+ * Input parameters:
+ * ops - file I/O dispatch
+ * ref - open file handle
+ * entrypt - filled in with entry vector
+ * flags - generic boot flags
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int elfload_internal(fileio_ctx_t *fsctx,void *ref,
+ long *entrypt,int flags)
+{
+ Elf32_Ehdr *ep;
+ Elf32_Phdr *phtab = 0;
+ Elf32_Shdr *shtab = 0;
+ unsigned int nbytes;
+ int i;
+ int res;
+ Elf32_Ehdr ehdr;
+
+ ep = &ehdr;
+ if (fs_read(fsctx,ref,(uint8_t *) ep,sizeof(*ep)) != sizeof(*ep)) {
+ return CFE_ERR_IOERR;
+ }
+
+ /* check header validity */
+ if (ep->e_ident[EI_MAG0] != ELFMAG0 ||
+ ep->e_ident[EI_MAG1] != ELFMAG1 ||
+ ep->e_ident[EI_MAG2] != ELFMAG2 ||
+ ep->e_ident[EI_MAG3] != ELFMAG3) {
+ return CFE_ERR_NOTELF;
+ }
+
+ if (ep->e_ident[EI_CLASS] != ELFCLASS32) return CFE_ERR_NOT32BIT;
+
+#ifdef __MIPSEB
+ if (ep->e_ident[EI_DATA] != ELFDATA2MSB) return CFE_ERR_WRONGENDIAN; /* big endian */
+#endif
+#ifdef __MIPSEL
+ if (ep->e_ident[EI_DATA] != ELFDATA2LSB) return CFE_ERR_WRONGENDIAN; /* little endian */
+#endif
+
+ if (ep->e_ident[EI_VERSION] != EV_CURRENT) return CFE_ERR_BADELFVERS;
+ if (ep->e_machine != EM_MIPS) return CFE_ERR_NOTMIPS;
+
+ /* Is there a program header? */
+ if (ep->e_phoff == 0 || ep->e_phnum == 0 ||
+ ep->e_phentsize != sizeof(Elf32_Phdr)) {
+ return CFE_ERR_BADELFFMT;
+ }
+
+ /* Load program header */
+ nbytes = ep->e_phnum * sizeof(Elf32_Phdr);
+ phtab = (Elf32_Phdr *) KMALLOC(nbytes,0);
+ if (!phtab) {
+ return CFE_ERR_NOMEM;
+ }
+
+ if (fs_seek(fsctx,ref,ep->e_phoff,FILE_SEEK_BEGINNING) != ep->e_phoff ||
+ fs_read(fsctx,ref,(uint8_t *)phtab,nbytes) != nbytes) {
+ KFREE(phtab);
+ return CFE_ERR_IOERR;
+ }
+
+ /*
+ * From now on we've got no guarantee about the file order,
+ * even where the section header is. Hopefully most linkers
+ * will put the section header after the program header, when
+ * they know that the executable is not demand paged. We assume
+ * that the symbol and string tables always follow the program
+ * segments.
+ */
+
+ /* read section table (if before first program segment) */
+ if (ep->e_shoff < phtab[0].p_offset) {
+ shtab = elfgetshdr(fsctx,ref,ep);
+ }
+
+ /* load program segments */
+ /* We cope with a badly sorted program header, as produced by
+ * older versions of the GNU linker, by loading the segments
+ * in file offset order, not in program header order. */
+
+ while (1) {
+ Elf32_Off lowest_offset = ~0;
+ Elf32_Phdr *ph = 0;
+
+ /* find nearest loadable segment */
+ for (i = 0; i < ep->e_phnum; i++)
+ if ((phtab[i].p_type == PT_LOAD) && (phtab[i].p_offset < lowest_offset)) {
+ ph = &phtab[i];
+ lowest_offset = ph->p_offset;
+ }
+ if (!ph) {
+ break; /* none found, finished */
+ }
+ /* load the segment */
+ if (ph->p_filesz) {
+ if (fs_seek(fsctx,ref,ph->p_offset,FILE_SEEK_BEGINNING) != ph->p_offset) {
+ if (shtab) KFREE(shtab);
+ KFREE(phtab);
+ return CFE_ERR_BADELFFMT;
+ }
+ res = readprogsegment(fsctx,ref,
+ (void *)(intptr_t)(signed)ph->p_vaddr,
+ ph->p_filesz,flags);
+ if (res != ph->p_filesz) {
+ if (shtab) KFREE(shtab);
+ KFREE(phtab);
+ return res;
+ }
+ }
+ if (ph->p_filesz < ph->p_memsz) {
+ res = readclearbss((void *)(intptr_t)(signed)ph->p_vaddr + ph->p_filesz,
+ ph->p_memsz - ph->p_filesz,flags);
+ if (res < 0) {
+ if (shtab) KFREE(shtab);
+ KFREE(phtab);
+ return res;
+ }
+ }
+
+ ph->p_type = PT_NULL; /* remove from consideration */
+ }
+
+ KFREE(phtab);
+
+ *entrypt = (intptr_t)ep->e_entry; /* return entry point */
+ return 0;
+}
+
+
+
+/* *********************************************************************
+ * cfe_elfload(ops,file,flags)
+ *
+ * Read an ELF file (main entry point)
+ *
+ * Input parameters:
+ * ops - fileio dispatch
+ * file - name of file to read
+ * ept - where to put entry point
+ * flags - load flags
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+int bcm63xx_cfe_elfload(cfe_loadargs_t *la)
+{
+ fileio_ctx_t *fsctx;
+ void *ref;
+ int res;
+
+ /*
+ * Look up the file system type and get a context
+ */
+
+
+ res = fs_init(la->la_filesys,&fsctx,la->la_device);
+ if (res != 0) {
+ return res;
+ }
+
+ /*
+ * Turn on compression if we're doing that.
+ */
+
+ if (la->la_flags & LOADFLG_COMPRESSED) {
+ res = fs_hook(fsctx,"z");
+ if (res != 0) {
+ return res;
+ }
+ }
+
+ /*
+ * Open the remote file
+ */
+
+ res = fs_open(fsctx,&ref,la->la_filename,FILE_MODE_READ);
+ if (res != 0) {
+ fs_uninit(fsctx);
+ return CFE_ERR_FILENOTFOUND;
+ }
+
+ /*
+ * Load the image.
+ */
+
+ la->la_entrypt = 0;
+ res = elfload_internal(fsctx,ref,&(la->la_entrypt),la->la_flags);
+
+ /*
+ * All done, release resources
+ */
+
+ fs_close(fsctx,ref);
+ fs_uninit(fsctx);
+
+ return res;
+}
+
+
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_raw.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_raw.c
new file mode 100755
index 0000000..eaabf14
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_raw.c
@@ -0,0 +1,368 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * RAW Program Loader File: cfe_ldr_raw.c
+ *
+ * This program reads raw binaries into memory.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_error.h"
+#include "cfe_devfuncs.h"
+
+#include "cfe.h"
+#include "cfe_fileops.h"
+
+#include "cfe_boot.h"
+#include "cfe_bootblock.h"
+
+#include "cfe_loader.h"
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+int bcm63xx_cfe_rawload(cfe_loadargs_t *la);
+
+const cfe_loader_t rawloader = {
+ "raw",
+ bcm63xx_cfe_rawload,
+ 0};
+
+/* *********************************************************************
+ * cfe_findbootblock(la,fsctx,ref)
+ *
+ * Find the boot block on the specified device.
+ *
+ * Input parameters:
+ * la - loader args (to be filled in)
+ * ops - file operations
+ * ref - reference for open file handle
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+static int cfe_findbootblock(cfe_loadargs_t *la,
+ fileio_ctx_t *fsctx,
+ void *ref,
+ struct boot_block *bootblock)
+{
+ uint32_t checksum = 0;
+ uint32_t calcsum = 0;
+ uint32_t secsize = 0;
+ uint64_t secoffset = 0;
+ int res;
+ int curblk;
+
+ /*
+ * Search for the boot block. Stop when we find
+ * something with a matching checksum and magic
+ * number.
+ */
+
+ fs_seek(fsctx,ref,0,FILE_SEEK_BEGINNING);
+
+ for (curblk = 0; curblk < BOOT_BLOCK_MAXLOC; curblk++) {
+
+
+ /* Read a block */
+
+ res = fs_read(fsctx,ref,
+ (unsigned char *) bootblock,
+ sizeof(struct boot_block));
+
+ if (res != sizeof(struct boot_block)) {
+ return CFE_ERR_IOERR;
+ }
+
+ /* Verify magic number */
+
+#if defined(CONFIG_MIPS_BRCM)
+ continue;
+#else
+ if (bootblock->bb_magic != BOOT_MAGIC_NUMBER) {
+ continue;
+ }
+#endif
+
+ /* Extract fields from block */
+
+ checksum = ((uint32_t) (bootblock->bb_hdrinfo & BOOT_HDR_CHECKSUM_MASK));
+ bootblock->bb_hdrinfo &= ~BOOT_HDR_CHECKSUM_MASK;
+ secsize = ((uint32_t) (bootblock->bb_secsize & BOOT_SECSIZE_MASK));
+ secoffset = bootblock->bb_secstart;
+
+ /* Verify block's checksum */
+
+ CHECKSUM_BOOT_DATA(&(bootblock->bb_magic),BOOT_BLOCK_SIZE,&calcsum);
+
+ if (checksum == calcsum) {
+ break;
+ }
+ }
+
+ /*
+ * Okay, determine if we were successful.
+ */
+
+#if !defined(CONFIG_MIPS_BRCM)
+ if (bootblock->bb_magic != BOOT_MAGIC_NUMBER) {
+ return CFE_ERR_INVBOOTBLOCK;
+ }
+#endif
+
+ if (checksum != calcsum) {
+ return CFE_ERR_BBCHECKSUM;
+ }
+
+ /*
+ * If we get here, we had a valid boot block.
+ */
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * cfe_rawload(la)
+ *
+ * Read a raw (unformatted) boot file
+ *
+ * Input parameters:
+ * la - loader args
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+int bcm63xx_cfe_rawload(cfe_loadargs_t *la)
+{
+ int res;
+ fileio_ctx_t *fsctx;
+ const fileio_dispatch_t *ops;
+ void *ref;
+ int ttlcopy = 0;
+ int findbb;
+ int devinfo;
+ struct boot_block bootblock;
+ uint8_t *ptr;
+ uint8_t *bootcode;
+#if !defined(CONFIG_MIPS_BRCM)
+ uint32_t checksum,calcsum;
+#endif
+ uint64_t secoffset = 0;
+ int32_t maxsize;
+ int amtcopy;
+ int thisamt;
+ uint32_t loadflags;
+ int onedot;
+
+ loadflags = la->la_flags;
+
+ /*
+ * Set starting address and maximum size. You can either
+ * explicitly set this (with LOADFLG_SPECADDR) or
+ * let CFE decide. If CFE decides, the load address
+ * will be BOOT_START_ADDRESS in all cases.
+ * The size is dependant on the device type: block and flash
+ * devices will get this info from the boot block,
+ * and network devices will get the info by reaching EOF
+ * on reads, up to the maximum size of the boot area.
+ */
+
+ if (loadflags & LOADFLG_SPECADDR) {
+ bootcode = (uint8_t *) la->la_address;
+ maxsize = la->la_maxsize;
+ findbb = FALSE; /* don't find a boot block */
+ }
+ else {
+ bootcode = (uint8_t *) BOOT_START_ADDRESS;
+ maxsize = BOOT_AREA_SIZE;
+ findbb = FALSE;
+ devinfo = la->la_device ? cfe_getdevinfo(la->la_device) : 0;
+
+ /*
+ * If the device is either a disk or a flash device,
+ * we will expect to find a boot block.
+ * Serial and network devices do not have boot blocks.
+ */
+ if ((devinfo >= 0) &&
+ ( ((devinfo & CFE_DEV_MASK) == CFE_DEV_DISK) ||
+ ((devinfo & CFE_DEV_MASK) == CFE_DEV_FLASH) )) {
+ findbb = TRUE;
+ }
+ }
+
+
+ /*
+ * merge in any filesystem-specific flags
+ */
+
+ ops = cfe_findfilesys(la->la_filesys);
+ if (!ops) return CFE_ERR_FSNOTAVAIL;
+ loadflags |= ops->loadflags;
+
+ /*
+ * turn off the boot block if requested.
+ */
+
+ if (loadflags & LOADFLG_NOBB) findbb = FALSE;
+
+ /*
+ * Create a file system context
+ */
+
+ res = fs_init(la->la_filesys,&fsctx,la->la_device);
+ if (res != 0) {
+ return res;
+ }
+
+ /*
+ * Turn on compression if we're doing that.
+ */
+
+ if (!findbb && (la->la_flags & LOADFLG_COMPRESSED)) {
+ res = fs_hook(fsctx,"z");
+ if (res != 0) {
+ return res;
+ }
+ }
+
+ /*
+ * Open the boot device
+ */
+
+ res = fs_open(fsctx,&ref,la->la_filename,FILE_MODE_READ);
+ if (res != 0) {
+ fs_uninit(fsctx);
+ return res;
+ }
+
+ /*
+ * If we need to find a boot block, do it now.
+ */
+
+ if (findbb) {
+ res = cfe_findbootblock(la,fsctx,ref,&bootblock);
+
+ /*
+ * If we found the boot block, seek to the part of the
+ * disk where the boot code is.
+ * Otherwise, get out now, since the disk has no boot block.
+ */
+
+ if (res == 0) {
+ maxsize = (int) ((uint32_t) (bootblock.bb_secsize & BOOT_SECSIZE_MASK));
+ secoffset = bootblock.bb_secstart;
+ fs_seek(fsctx,ref,secoffset,FILE_SEEK_BEGINNING);
+ }
+ else {
+ fs_close(fsctx,ref);
+ fs_uninit(fsctx);
+ return res;
+ }
+
+ }
+
+ /*
+ * Okay, go load the boot file.
+ */
+
+ ptr = bootcode;
+ amtcopy = maxsize;
+ ttlcopy = 0;
+
+ onedot = amtcopy / 10; /* ten dots for entire load */
+ if (onedot < 4096) onedot = 4096; /* but minimum 4096 bytes per dot */
+ onedot = (onedot + 1) & ~4095; /* round to multiple of 4096 */
+
+ while (amtcopy > 0) {
+ thisamt = onedot;
+ if (thisamt > amtcopy) thisamt = amtcopy;
+
+ res = fs_read(fsctx,ref,ptr,thisamt);
+ if (la->la_flags & LOADFLG_NOISY) {
+ xprintf(".");
+ }
+ if (res <= 0) break;
+ ptr += res;
+ amtcopy -= res;
+ ttlcopy += res;
+ }
+
+ /*
+ * We're done with the file.
+ */
+
+ fs_close(fsctx,ref);
+ fs_uninit(fsctx);
+
+ /*
+ * Verify the boot loader checksum if we were reading
+ * the disk.
+ */
+
+#if !defined(CONFIG_MIPS_BRCM)
+ if (findbb) {
+ CHECKSUM_BOOT_DATA(bootcode,maxsize,&calcsum);
+ checksum = (uint32_t) ((bootblock.bb_secsize & BOOT_DATA_CHECKSUM_MASK)
+ >> BOOT_DATA_CHECKSUM_SHIFT);
+
+ if (checksum != calcsum) {
+ return CFE_ERR_BOOTPROGCHKSUM;
+ }
+ }
+#endif
+
+ la->la_entrypt = (uintptr_t) bootcode;
+
+ if (la->la_flags & LOADFLG_NOISY) xprintf(" %d bytes read\n",ttlcopy);
+
+ return (res < 0) ? res : ttlcopy;
+
+}
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_main.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_main.c
new file mode 100755
index 0000000..2cf2546
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_main.c
@@ -0,0 +1,611 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Main Module File: cfe_main.c
+ *
+ * This module contains the main "C" routine for CFE and
+ * the main processing loop. There should not be any board-specific
+ * stuff in here.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_timer.h"
+
+#include "env_subr.h"
+#include "cfe_mem.h"
+#include "cfe.h"
+
+#include "exception.h"
+
+#include "bsp_config.h"
+#include "bcm_hwdefs.h"
+#include "boardparms.h"
+#include "bcm_map.h"
+#include "bcm_cpu.h"
+#include "bcm63xx_util.h"
+
+#include "segtable.h"
+#include "initdata.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#ifndef CFG_STACK_SIZE
+#define STACK_SIZE 8192
+#else
+#define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023)
+#endif
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+void cfe_main(int,int);
+void cfe_command_restart(uint64_t status);
+
+extern void cfe_device_poll(void *x);
+
+extern int cfe_web_check(void);
+extern void cfe_web_fg_process(void);
+extern void cfe_web_poll(void *x);
+
+extern const char *builddate;
+extern const char *builduser;
+
+/* Foxconn add start by Cliff Wang, 03/23/2010 */
+extern int ui_init_netcmds(void);
+/* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+const char *cfe_boardname = CFG_BOARDNAME;
+unsigned int cfe_startflags = 0;
+#if defined (_BCM96368_)
+static int cfe_bus_speed = 0;
+static int cfe_ref_speed = 0;
+#endif
+#if defined (_BCM96328_) || defined (_BCM96362_) || defined (_BCM96816_)
+static int cfe_bus_speed = 0;
+static int cfe_ddr_speed = 0;
+#endif
+unsigned long cfe_sdramsize = 8 * 1024 * 1024;
+
+static void calculateCpuSpeed(void);
+
+#if defined (_BCM96328_)
+const uint32 cpu_speed_table[0x20] = {
+ 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320,
+ 0, 320, 160, 200, 160, 200, 400, 320, 320, 160, 384, 320, 192, 320, 320, 320
+};
+const uint32 ddr_speed_table[0x20] = {
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 0, 80, 100, 100, 160, 200, 400, 400, 80, 160, 160, 160, 192, 192, 240, 320
+};
+const uint32 bus_speed_table[0x20] = {
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 0, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160
+};
+#endif
+
+#if defined (_BCM96362_)
+const uint32 cpu_speed_table[0x20] = {
+ 320, 320, 320, 240, 160, 400, 440, 384, 320, 320, 320, 240, 160, 320, 400, 320,
+ 320, 320, 320, 240, 160, 200, 400, 384, 320, 320, 320, 240, 160, 200, 400, 400
+};
+const uint32 ddr_speed_table[0x20] = {
+ 320, 400, 192, 320, 200, 400, 367, 320, 320, 400, 192, 320, 200, 400, 400, 320,
+ 320, 400, 192, 320, 200, 267, 400, 320, 320, 320, 192, 320, 200, 200, 400, 333
+};
+const uint32 bus_speed_table[0x20] = {
+ 160, 200, 96, 160, 100, 160, 183, 160, 160, 200, 96, 160, 100, 160, 200, 160,
+ 160, 200, 96, 160, 100, 100, 200, 160, 160, 160, 96, 160, 100, 100, 200, 166
+};
+#endif
+
+#if defined (_BCM96816_)
+const uint32 cpu_speed_table[0x20] = {
+ 200, 400, 400, 320, 200, 400, 333, 333, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 400, 400, 200, 360, 400, 400, 300, 300, 320, 320, 400, 400
+};
+const uint32 ddr_speed_table[0x20] = {
+ 200, 333, 200, 200, 200, 333, 333, 333, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 400, 200, 200, 300, 300, 300, 300, 300, 400, 400, 400, 400
+};
+const uint32 bus_speed_table[0x20] = {
+ 200, 200, 200, 160, 100, 167, 200, 167, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 200, 200, 160, 180, 171, 200, 171, 200, 160, 200, 160, 200
+};
+#endif
+
+static unsigned long cfe_get_sdram_size(void);
+
+/* *********************************************************************
+ * cfe_setup_default_env()
+ *
+ * Initialize the default environment for CFE. These are all
+ * the temporary variables that do not get stored in the NVRAM
+ * but are available to other programs and command-line macros.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void cfe_setup_default_env(void)
+{
+ char buffer[80];
+
+ xsprintf(buffer,"%d.%d.%d",CFE_VER_MAJOR,CFE_VER_MINOR,CFE_VER_BUILD);
+ env_setenv("CFE_VERSION",buffer,ENV_FLG_BUILTIN | ENV_FLG_READONLY);
+
+ if (cfe_boardname) {
+ env_setenv("CFE_BOARDNAME",(char *) cfe_boardname,
+ ENV_FLG_BUILTIN | ENV_FLG_READONLY);
+ }
+}
+
+
+/* *********************************************************************
+ * cfe_ledstr(leds)
+ *
+ * Display a string on the board's LED display, if it has one.
+ * This routine depends on the board-support package to
+ * include a "driver" to write to the actual LED, if the board
+ * does not have one this routine will do nothing.
+ *
+ * The LEDs are written at various places in the initialization
+ * sequence, to debug board problems.
+ *
+ * Input parameters:
+ * leds - pointer to four-character ASCII string
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_ledstr(const char *leds)
+{
+#if 0
+ unsigned int val;
+
+ val = ((((unsigned int) leds[0]) << 24) |
+ (((unsigned int) leds[1]) << 16) |
+ (((unsigned int) leds[2]) << 8) |
+ ((unsigned int) leds[3]));
+
+ cfe_leds(val);
+#endif
+}
+
+
+/* *********************************************************************
+ * cfe_say_hello()
+ *
+ * Print out the CFE startup message and copyright notice
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_command_restart(uint64_t status)
+{
+}
+
+static void cfe_say_hello(void)
+{
+ xprintf("\n\n");
+ xprintf("CFE version 2.0.3"
+#ifdef CFE_VER_RELEASE
+ ".%d"
+#endif
+ " for DGN2200v2 (%s)\n",
+ //CFE_VER_MAJOR,CFE_VER_MINOR,CFE_VER_BUILD, BCM63XX_MAJOR, BCM63XX_MINOR,
+#ifdef CFE_VER_RELEASE
+ CFE_VER_RELEASE,
+#endif
+ //cfe_boardname,
+#ifdef __long64
+ "64bit,"
+#else
+ "32bit,"
+#endif
+#if CFG_MULTI_CPUS
+ "MP,"
+#else
+ "SP,"
+#endif
+#ifdef __MIPSEL
+ "LE"
+#endif
+#ifdef __MIPSEB
+ "BE"
+#endif
+#if CFG_VAPI
+ ",VAPI"
+#endif
+ );
+
+ xprintf("Build Date: %s (%s)\n",builddate,builduser);
+ xprintf("Copyright (C) 2000-2009 Broadcom Corporation.\n");
+ xprintf("\n");
+}
+
+
+/* *********************************************************************
+ * cfe_restart()
+ *
+ * Restart CFE from scratch, jumping back to the boot vector.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+void cfe_restart(void)
+{
+ _exc_restart();
+}
+
+
+/* *********************************************************************
+ * cfe_start(ept)
+ *
+ * Start a user program
+ *
+ * Input parameters:
+ * ept - entry point
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+void cfe_start(unsigned long ept)
+{
+ cfe_launch(ept);
+}
+
+/* *********************************************************************
+ * cfe_startup_info()
+ *
+ * Display startup memory configuration messages
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void cfe_startup_info(void)
+{
+ xprintf("Chip ID: BCM%X%X, ", (PERF->RevID & 0xFFFF0000) >> 16, PERF->RevID & 0xFF);
+ xprintf("MIPS: %dMHz",cfe_cpu_speed/1000000);
+#if defined (_BCM96328_) || defined (_BCM96362_) || defined (_BCM96816_)
+ xprintf(", DDR: %dMHz, Bus: %dMHz\n", cfe_ddr_speed/1000000, cfe_bus_speed/1000000);
+#else
+ xprintf("\n");
+#endif
+ {
+ unsigned long tp;
+ __asm __volatile(
+ "mfc0 $9, $22, 3;"
+ "move %0, $9"
+ :"=r" (tp));
+ tp = ((tp & CP0_CMT_TPID) == CP0_CMT_TPID) ? 1 : 0;
+ xprintf("Main Thread: TP%d\n", tp);
+ }
+#if defined (_BCM96328_) || defined (_BCM96362_) || defined (_BCM96816_)
+ if (DDR->TEST_CFG1 & 0x2) { /* Memory Test is finished */
+ xprintf("Memory Test ");
+ if (DDR->TEST_CFG1 & 0x4) {
+ xprintf("Failed\n");
+ }
+ else {
+ xprintf("Passed\n");
+ }
+ }
+#endif
+ cfe_sdramsize = cfe_get_sdram_size();
+ xprintf("Total Memory: %lu bytes (%luMB)\n", cfe_sdramsize, cfe_sdramsize >> 20);
+ xprintf("Boot Address: 0x%x\n\n", FLASH_BASE);
+}
+
+#if defined (_BCM96816_)
+/* *********************************************************************
+ * apm_hvg_init()
+ *
+ * Work around 6816-specific reset logic
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+static void apm_hvg_init(void)
+{
+ HVG->reg_hvg_cha_misc ^= HVG_SOFT_INIT_0;
+ HVG->reg_hvg_chb_misc ^= HVG_SOFT_INIT_0;
+}
+#endif
+
+/* *********************************************************************
+ * cfe_main(a,b)
+ *
+ * It's gotta start somewhere.
+ *
+ * Input parameters:
+ * a,b - not used
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+void cfe_main(int a,int b)
+{
+ /*
+ * By the time this routine is called, the following things have
+ * already been done:
+ *
+ * 1. The processor(s) is(are) initialized.
+ * 2. The caches are initialized.
+ * 3. The memory controller is initialized.
+ * 4. BSS has been zeroed.
+ * 5. The data has been moved to R/W space.
+ * 6. The "C" Stack has been initialized.
+ */
+
+ cfe_bg_init(); /* init background processing */
+ cfe_attach_init();
+ calculateCpuSpeed();
+ cfe_timer_init(); /* Timer process */
+ cfe_bg_add(cfe_device_poll,NULL);
+
+ /*
+ * Initialize the memory allocator
+ */
+ KMEMINIT((unsigned char *) (uintptr_t) mem_heapstart,
+ ((CFG_HEAP_SIZE)*1024));
+
+ /*
+ * Initialize the console. It is done before the other devices
+ * get turned on.
+ */
+
+ board_console_init();
+ cfe_setup_exceptions();
+ cfe_say_hello();
+
+#if defined(CONFIG_BRCM_IKOS)
+ {
+ /*0x694b6f32 (iKo2) is replaced with actual addr during the build process*/
+ static unsigned long linuxStartAddr=0x694b6f32;
+ printf("IKOS Build: Jump to Linux start address 0x%8.8lx.\n\n",
+ linuxStartAddr);
+ cfe_launch(linuxStartAddr);
+ }
+#endif
+
+ cfe_arena_init();
+ board_device_init();
+ cfe_startup_info();
+ cfe_setup_default_env();
+ ui_init_cmddisp();
+ getBootLine();
+ getBoardParam();
+#if defined (_BCM96816_)
+ apm_hvg_init();
+#endif
+
+ /* Foxconn add start by Cliff Wang, 03/23/2010 */
+ ui_init_netcmds();
+ /* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+ board_final_init();
+ cfe_command_loop();
+
+
+}
+
+
+/* *********************************************************************
+ * cfe_command_loop()
+ *
+ * This routine reads and processes user commands
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+void cfe_command_loop()
+{
+ char buffer[300];
+ int status;
+ char *prompt;
+
+ /* Start Web interface. */
+ cfe_bg_add(cfe_web_poll,NULL);
+
+ for (;;) {
+ prompt = env_getenv("PROMPT");
+ if (!prompt) prompt = "CFE> ";
+ console_readline(prompt,buffer,sizeof(buffer));
+
+ if (cfe_web_check())
+ cfe_web_fg_process();
+ else {
+ status = ui_docommands(buffer);
+ if (status != CMD_ERR_BLANK) {
+ xprintf("*** command status = %d\n", status);
+ }
+ }
+ }
+}
+
+/* *********************************************************************
+ * cfe_errortext(err)
+ *
+ * Returns an error message with a number in it. The number can be
+ * looked up in cfe_error.h.
+ *
+ * Input parameters:
+ * err - error code
+ *
+ * Return value:
+ * string description of error
+ ********************************************************************* */
+
+const char *cfe_errortext(int err)
+{
+ static char err_buf[20];
+
+ sprintf(err_buf, "CFE error %d", err);
+ return (const char *) err_buf;
+}
+
+#if defined (_BCM96368_)
+/* *********************************************************************
+ * calculateCpuSpeed()
+ * Calculate BCM6368 CPU speed by reading the PLL Config register
+ * and applying the following formula:
+ * Fref_clk = (64 * (P2/P1) * (MIPSDDR_NDIV / REF_MDIV)
+ * Fbus_clk = (64 * (P2/P1) * (MIPSDDR_NDIV / DDR_MDIV)
+ * Fcpu_clk = (64 * (P2/P1) * (MIPSDDR_NDIV / CPU_MDIV)
+ * Input parameters:
+ * none
+ * Return value:
+ * none
+ ********************************************************************* */
+void static calculateCpuSpeed(void)
+{
+ UINT32 numerator;
+ UINT32 pllConfig = DDR->MIPSDDRPLLConfig;
+ UINT32 pllMDiv = DDR->MIPSDDRPLLMDiv;
+
+ numerator = 64000000 / ((pllConfig & MIPSDDR_P1_MASK) >> MIPSDDR_P1_SHFT) *
+ ((pllConfig & MIPSDDR_P2_MASK) >> MIPSDDR_P2_SHFT) *
+ ((pllConfig & MIPSDDR_NDIV_MASK) >> MIPSDDR_NDIV_SHFT);
+
+ cfe_cpu_speed = numerator / ((pllMDiv & MIPS_MDIV_MASK) >> MIPS_MDIV_SHFT);
+ cfe_bus_speed = numerator / ((pllMDiv & DDR_MDIV_MASK) >> DDR_MDIV_SHFT);
+ cfe_ref_speed = numerator / ((pllConfig & REF_MDIV_MASK) >> REF_MDIV_SHFT);
+}
+#endif
+
+#if defined (_BCM96328_) || defined (_BCM96362_) || (_BCM96816_)
+/* *********************************************************************
+ * calculateCpuSpeed()
+ * Calculate CPU speed by reading strap register
+ * Input parameters:
+ * none
+ * Return value:
+ * none
+ ********************************************************************* */
+void static calculateCpuSpeed(void)
+{
+ uint32 mips_pll_fvco;
+
+ mips_pll_fvco = MISC->miscStrapBus & MISC_STRAP_BUS_MIPS_PLL_FVCO_MASK;
+ mips_pll_fvco >>= MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT;
+ cfe_cpu_speed = cpu_speed_table[mips_pll_fvco] * 1000000;
+ cfe_ddr_speed = ddr_speed_table[mips_pll_fvco] * 1000000;
+ cfe_bus_speed = bus_speed_table[mips_pll_fvco] * 1000000;
+}
+#endif
+
+/* *********************************************************************
+ * cfe_get_sdram_size(void)
+ *
+ * Return amount of SDRAM on the board.
+ *
+ * Input parameters:
+ * None.
+ *
+ * Return value:
+ * Amount of SDRAM on the board.
+ ********************************************************************* */
+static unsigned long cfe_get_sdram_size(void)
+{
+#if defined (_BCM96368_)
+ uint32 size;
+ uint32 memCfg;
+
+ size = 1;
+ memCfg = MEMC->Config;
+ /* Number of column bits */
+ size <<= (((memCfg & MEMC_COL_MASK) >> MEMC_COL_SHFT) + 8);
+ /* Plus number of row bits */
+ size <<= (((memCfg & MEMC_ROW_MASK) >> MEMC_ROW_SHFT) + 11);
+ /* Plus bus width */
+ if (((memCfg & MEMC_WIDTH_MASK) >> MEMC_WIDTH_SHFT) == MEMC_32BIT_BUS)
+ size <<= 2;
+ else
+ size <<= 1;
+
+ /* Plus number of banks */
+ size <<= 2;
+
+ return( size );
+#else
+ return (DDR->CSEND << 24);
+#endif
+}
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_net_icmp.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_net_icmp.c
new file mode 100755
index 0000000..89802f8
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_net_icmp.c
@@ -0,0 +1,199 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * ICMP Protocol File: net_icmp.c
+ *
+ * This module implements portions of the ICMP protocol. Note
+ * that it is not a complete implementation, just enough to
+ * generate and respond to ICMP echo requests.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_timer.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+
+#include "net_ip.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define ICMP_CODE_ECHO 0
+#define ICMP_TYPE_ECHOREPLY 0
+#define ICMP_TYPE_ECHOREQ 8
+
+#define ICMPMSG(type,code) (((type)<<8)|(code))
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+struct icmp_info_s {
+ ip_info_t *icmp_ipinfo;
+ queue_t icmp_echoreplies;
+ int icmp_maxreplies;
+};
+
+/* *********************************************************************
+ * ICMP_RX_CALLBACK(ref,buf,dst,src)
+ *
+ * This routine is called by the IP layer when we receive
+ * ICMP protocol messages.
+ *
+ * Input parameters:
+ * ref - reference data (an icmp_info_t)
+ * buf - the ebuf containing the buffer
+ * dst - destination IP address (us, usually)
+ * src - source IP address
+ *
+ * Return value:
+ * ETH_KEEP to keep packet, ETH_DROP to cause packet to be freed
+ ********************************************************************* */
+
+static int icmp_rx_callback(void *ref,ebuf_t *buf,uint8_t *dst,uint8_t *src)
+{
+ icmp_info_t *icmp = (icmp_info_t *)ref;
+ ip_info_t *ipi = icmp->icmp_ipinfo;
+ uint16_t imsg;
+ uint16_t cksum;
+ ebuf_t *txbuf;
+ uint8_t *icmphdr;
+ int res;
+
+ imsg = ICMPMSG(buf->eb_ptr[0],buf->eb_ptr[1]);
+
+ res = ETH_DROP; /* assume we're dropping the pkt */
+
+ switch (imsg) {
+ case ICMPMSG(ICMP_TYPE_ECHOREQ,ICMP_CODE_ECHO):
+ txbuf = _ip_alloc(ipi);
+ if (txbuf) {
+ /* Construct reply from the original packet. */
+ icmphdr = txbuf->eb_ptr;
+ ebuf_append_bytes(txbuf,buf->eb_ptr,buf->eb_length);
+ icmphdr[0] = ICMP_TYPE_ECHOREPLY;
+ icmphdr[1] = ICMP_CODE_ECHO;
+ icmphdr[2] = 0; icmphdr[3] = 0;
+ cksum = ~ip_chksum(0,icmphdr,ebuf_length(txbuf));
+ icmphdr[2] = (cksum >> 8) & 0xFF;
+ icmphdr[3] = (cksum & 0xFF);
+ if (_ip_send(ipi,txbuf,src,IPPROTO_ICMP) < 0) {
+ _ip_free(ipi,txbuf);
+ }
+ }
+ break;
+
+ case ICMPMSG(ICMP_TYPE_ECHOREPLY,ICMP_CODE_ECHO):
+ if (q_count(&(icmp->icmp_echoreplies)) < icmp->icmp_maxreplies) {
+ /* We're keeping this packet, put it on the queue and don't
+ free it in the driver. */
+ q_enqueue(&(icmp->icmp_echoreplies),(queue_t *) buf);
+ res = ETH_KEEP;
+ }
+ break;
+
+ default:
+ res = ETH_DROP;
+ }
+
+ return res;
+}
+
+
+/* *********************************************************************
+ * _ICMP_INIT(ipi)
+ *
+ * Initialize the ICMP layer.
+ *
+ * Input parameters:
+ * ipi - ipinfo structure of IP layer to attach to
+ *
+ * Return value:
+ * icmp_info_t structure or NULL if error occurs
+ ********************************************************************* */
+
+icmp_info_t *_icmp_init(ip_info_t *ipi)
+{
+ icmp_info_t *icmp;
+
+ icmp = (icmp_info_t *) KMALLOC(sizeof(icmp_info_t),0);
+ if (!icmp) return NULL;
+
+ icmp->icmp_ipinfo = ipi;
+ q_init(&(icmp->icmp_echoreplies));
+ icmp->icmp_maxreplies = 0;
+
+ _ip_register(ipi,IPPROTO_ICMP,icmp_rx_callback,icmp);
+
+ return icmp;
+}
+
+/* *********************************************************************
+ * _ICMP_UNINIT(icmp)
+ *
+ * Un-initialize the ICMP layer.
+ *
+ * Input parameters:
+ * icmp - icmp_info_t structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void _icmp_uninit(icmp_info_t *icmp)
+{
+ _ip_deregister(icmp->icmp_ipinfo,IPPROTO_ICMP);
+
+ KFREE(icmp);
+}
+
+int _icmp_ping(icmp_info_t *icmp,uint8_t *dest,int seq,int len)
+{
+ return 0;
+}
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ram_boot.S b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ram_boot.S
new file mode 100755
index 0000000..cf48de0
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ram_boot.S
@@ -0,0 +1,88 @@
+#include "sbmips.h"
+
+/* *********************************************************************
+ * BOARD_EARLYINIT()
+ *
+ * Initialize board registers. This is the earliest
+ * time the BSP gets control. This routine cannot assume that
+ * memory is operational, and therefore all code in this routine
+ * must run from registers only. The $ra register must not
+ * be modified, as it contains the return address.
+ *
+ * This routine will be called from uncached space, before
+ * the caches are initialized. If you want to make
+ * subroutine calls from here, you must use the CALLKSEG1 macro.
+ *
+ * Among other things, this is where the GPIO registers get
+ * programmed to make on-board LEDs function, or other startup
+ * that has to be done before anything will work.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+LEAF(board_earlyinit)
+ j ra
+END(board_earlyinit)
+
+/* *********************************************************************
+ * BOARD_DRAMINFO
+ *
+ * Return the address of the DRAM information table
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * v0 - DRAM info table, return 0 to use default table
+ ********************************************************************* */
+LEAF(board_draminfo)
+ j ra
+END(board_draminfo)
+
+/* *********************************************************************
+ * BOARD_DRAMINIT
+ *
+ * This routine should activate memory.
+ *
+ * Input parameters:
+ * a0 - points to configuration table returned by board_draminfo
+ * or 0 to use an automatic table
+ *
+ * Return value:
+ * v0 - total memory installed
+ *
+ * Registers used:
+ * can use all registers.
+ ********************************************************************* */
+LEAF(board_draminit)
+ j ra
+END(board_draminit)
+
+/* *********************************************************************
+ * BOARD_SETLEDS(x)
+ *
+ * Set LEDs for boot-time progress indication. Not used if
+ * the board does not have progress LEDs. This routine
+ * must not call any other routines, since it may be invoked
+ * either from KSEG0 or KSEG1 and it may be invoked
+ * whether or not the icache is operational.
+ *
+ * Input parameters:
+ * a0 - LED value (8 bits per character, 4 characters)
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * t0,t1,t2,t3
+ ********************************************************************* */
+LEAF(board_setleds)
+ j ra
+END(board_setleds)
+
+LEAF(bcmcore_tp1_switch)
+ j ra
+END(bcmcore_tp1_switch)
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_util.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_util.c
new file mode 100755
index 0000000..91e1ad0
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_util.c
@@ -0,0 +1,1375 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * bcm63xx utility functions
+ *
+ * Created on : 04/18/2002 seanl
+ *
+ *********************************************************************
+
+<:copyright-broadcom
+
+ Copyright (c) 2002 Broadcom Corporation
+ All Rights Reserved
+ No portions of this material may be reproduced in any form without the
+ written permission of:
+ Broadcom Corporation
+ 16215 Alton Parkway
+ Irvine, California 92619
+ All information contained in this document is Broadcom Corporation
+ company private, proprietary, and trade secret.
+
+:>
+*/
+
+#define BCMTAG_EXE_USE
+#include "bcm63xx_util.h"
+#include "flash_api.h"
+#include "jffs2.h"
+
+#define je16_to_cpu(x) ((x).v16)
+#define je32_to_cpu(x) ((x).v32)
+
+static void convertBootInfo(void);
+static int checkChipId(int tagChipId, char *sig2);
+static void UpdateImageSequenceNumber( char *imageSequence );
+
+BOOT_INFO bootInfo;
+
+static int parseFilename(char *fn)
+{
+ if (strlen(fn) < BOOT_FILENAME_LEN)
+ return 0;
+ else
+ return 1;
+}
+
+static int parseChoiceFh(char *choice)
+{
+
+ if (*choice == 'f' || *choice == 'h')
+ return 0;
+ else
+ return 1;
+}
+
+
+static int parseBootPartition(char *choice)
+{
+ return( (*choice == BOOT_LATEST_IMAGE || *choice == BOOT_PREVIOUS_IMAGE)
+ ? 0 : 1 );
+}
+
+static int parseChoice09(char *choice)
+{
+ int bChoice = *choice - '0';
+
+ if (bChoice >= 0 && bChoice <= 9)
+ return 0;
+ else
+ return 1;
+}
+
+static int parseIpAddr(char *ipStr);
+static int parseGwIpAddr(char *ipStr);
+static int parseAfeId(char *afeIdStr);
+
+#define PARAM_IDX_BOARD_IPADDR 0
+#define PARAM_IDX_HOST_IPADDR 1
+#define PARAM_IDX_GW_IPADDR 2
+#define PARAM_IDX_RUN_FROM 3
+#define PARAM_IDX_RUN_FILENAME 4
+#define PARAM_IDX_FLASH_FILENAME 5
+#define PARAM_IDX_BOOT_DELAY 6
+#define PARAM_IDX_BOOT_IMAGE 7
+
+static PARAMETER_SETTING gBootParam[] =
+{
+ // prompt name Error Prompt Boot Define Boot Param Validation function
+ {"Board IP address :", IP_PROMPT , "e=",
+ "", 24, parseIpAddr, TRUE}, // index 0
+ {"Host IP address :", IP_PROMPT , "h=",
+ "", 15, parseIpAddr, TRUE}, // index 1
+ {"Gateway IP address :", IP_PROMPT , "g=",
+ "", 15, parseGwIpAddr, TRUE}, // index 2
+ {"Run from flash/host (f/h) :", RUN_FROM_PROMPT , "r=",
+ "", 1, parseChoiceFh, TRUE}, // index 3
+ {"Default host run file name :", HOST_FN_PROMPT , "f=",
+ "", MAX_PROMPT_LEN - 1, parseFilename, TRUE}, // index 4
+ {"Default host flash file name :", FLASH_FN_PROMPT , "i=",
+ "", MAX_PROMPT_LEN - 1, parseFilename, TRUE}, // index 5
+ {"Boot delay (0-9 seconds) :", BOOT_DELAY_PROMPT, "d=",
+ "", 1, parseChoice09, TRUE}, // index 6
+ {"Boot image (0=latest, 1=previous) :", BOOT_PARTITION_PROMPT, "p=",
+ "", 1, parseBootPartition, TRUE}, // index 7
+ {NULL},
+};
+
+static int gNumBootParams = (sizeof(gBootParam) / sizeof(PARAMETER_SETTING))-1;
+
+static PARAMETER_SETTING gAfeId[] =
+{
+ // prompt name Error Prompt Boot Define Boot Param Validation function
+ {"Primary AFE ID :", AFE_PROMPT, "", "", 12, parseAfeId, TRUE}, // index 0
+ {"Bonding AFE ID :", AFE_PROMPT, "", "", 12, parseAfeId, TRUE}, // index 1
+ {NULL},
+};
+static int gAfeIdParams = (sizeof(gAfeId) / sizeof(PARAMETER_SETTING))-1;
+
+// move from lib_misc.c
+int parseipaddr(const char *ipaddr,uint8_t *dest)
+{
+ int a,b,c,d;
+ char *x;
+
+ /* make sure it's all digits and dots. */
+ x = (char *) ipaddr;
+ while (*x) {
+ if ((*x == '.') || ((*x >= '0') && (*x <= '9'))) {
+ x++;
+ continue;
+ }
+ return -1;
+ }
+
+ x = (char *) ipaddr;
+ a = lib_atoi(ipaddr);
+ x = lib_strchr(x,'.');
+ if (!x) return -1;
+ b = lib_atoi(x+1);
+ x = lib_strchr(x+1,'.');
+ if (!x) return -1;
+ c = lib_atoi(x+1);
+ x = lib_strchr(x+1,'.');
+ if (!x) return -1;
+ d = lib_atoi(x+1);
+
+ if ((a < 0) || (a > 255)) return -1;
+ if ((b < 0) || (b > 255)) return -1;
+ if ((c < 0) || (c > 255)) return -1;
+ if ((d < 0) || (d > 255)) return -1;
+
+ dest[0] = (uint8_t) a;
+ dest[1] = (uint8_t) b;
+ dest[2] = (uint8_t) c;
+ dest[3] = (uint8_t) d;
+
+ return 0;
+}
+
+#if 0
+static const char hextable[16] = "0123456789ABCDEF";
+void dumpHex(unsigned char *start, int len)
+{
+ unsigned char *ptr = start,
+ *end = start + len;
+
+ while (ptr < end)
+ {
+ long offset = ptr - start;
+ unsigned char text[120],
+ *p = text;
+ while (ptr < end && p < &text[16 * 3])
+ {
+ *p++ = hextable[*ptr >> 4];
+ *p++ = hextable[*ptr++ & 0xF];
+ *p++ = ' ';
+ }
+ p[-1] = 0;
+ printf("%4lX %s\n", offset, text);
+ }
+}
+
+#endif
+
+int parsexdigit(char str)
+{
+ int digit;
+
+ if ((str >= '0') && (str <= '9'))
+ digit = str - '0';
+ else if ((str >= 'a') && (str <= 'f'))
+ digit = str - 'a' + 10;
+ else if ((str >= 'A') && (str <= 'F'))
+ digit = str - 'A' + 10;
+ else
+ return -1;
+
+ return digit;
+}
+
+
+// convert in = fffffff00 to out=255.255.255.0
+// return 0 = OK, 1 failed.
+static int convertMaskStr(char *in, char *out)
+{
+ int i;
+ char twoHex[4];
+ uint8_t dest[4];
+ char mask[BOOT_IP_LEN];
+
+ if (strlen(in) != MASK_LEN) // mask len has to 8
+ return 1;
+
+ memset(twoHex, 0, sizeof(twoHex));
+ for (i = 0; i < 4; i++)
+ {
+ twoHex[0] = (uint8_t)*in++;
+ twoHex[1] = (uint8_t)*in++;
+ if (parsexdigit(*twoHex) == -1)
+ return 1;
+ dest[i] = (uint8_t) xtoi(twoHex);
+ }
+ sprintf(mask, "%d.%d.%d.%d", dest[0], dest[1], dest[2], dest[3]);
+ strcpy(out, mask);
+ return 0;
+}
+
+// return 0 - OK, !0 - Bad ip
+static int parseIpAddr(char *ipStr)
+{
+ char *x;
+ uint8_t dest[4];
+ char mask[BOOT_IP_LEN];
+ char ipMaskStr[2*BOOT_IP_LEN];
+
+ strcpy(ipMaskStr, ipStr);
+
+ x = strchr(ipMaskStr,':');
+ if (!x) // no mask
+ return parseipaddr(ipMaskStr, dest);
+
+ *x = '\0';
+
+ if (parseipaddr(ipMaskStr, dest)) // ipStr is not ok
+ return 1;
+
+ x++;
+ return convertMaskStr(x, mask); // mask is not used here
+
+}
+
+// return 0 - OK, !0 - Bad ip
+static int parseGwIpAddr(char *ipStr)
+{
+ int ret = 0;
+ if( *ipStr )
+ ret = parseIpAddr(ipStr);
+ return(ret);
+}
+
+// return 0 - OK, !0 - Bad ip
+static int parseAfeId(char *afeIdStr)
+{
+ return 0;
+}
+
+// port from ifconfig command in ui_netcmds.c
+void enet_init(void)
+{
+ char devname[] = "eth0";
+ uint8_t addr[IP_ADDR_LEN];
+ int res;
+ NVRAM_DATA nvramData;
+
+ readNvramData(&nvramData);
+
+ if (net_getparam(NET_DEVNAME) == NULL) {
+ res = net_init(devname); /* turn interface on */
+ if (res < 0) {
+ ui_showerror(res, "Could not activate network interface '%s'", devname);
+ return;
+ }
+ }
+
+ net_setparam(NET_HWADDR, nvramData.ucaBaseMacAddr);
+
+ parseipaddr(bootInfo.boardIp, addr);
+ net_setparam(NET_IPADDR, addr);
+
+ if (strlen(bootInfo.boardMask) > 0) {
+ parseipaddr(bootInfo.boardMask, addr);
+ net_setparam(NET_NETMASK, addr);
+ }
+
+ if (strlen(bootInfo.gatewayIp) > 0) {
+ parseipaddr(bootInfo.gatewayIp, addr);
+ net_setparam(NET_GATEWAY, addr);
+ }
+
+ net_setnetvars();
+}
+
+/***************************************************************************
+// Function Name: getCrc32
+// Description : caculate the CRC 32 of the given data.
+// Parameters : pdata - array of data.
+// size - number of input data bytes.
+// crc - either CRC32_INIT_VALUE or previous return value.
+// Returns : crc.
+****************************************************************************/
+UINT32 getCrc32(byte *pdata, UINT32 size, UINT32 crc)
+{
+ while (size-- > 0)
+ crc = (crc >> 8) ^ Crc32_table[(crc ^ *pdata++) & 0xff];
+
+ return crc;
+}
+
+
+// return 0, ok. return -1 = wrong chip
+static int checkChipId(int tagChipId, char *sig2)
+{
+ unsigned int chipId = (PERF->RevID & 0xFFFE0000) >> 16;
+ int result = 0;
+
+ /* Force BCM681x variants to be be BCM6816) */
+ if( (chipId & 0xfff0) == 0x6810 )
+ chipId = 0x6816;
+
+ if (tagChipId == chipId)
+ result = 0;
+ else {
+ printf("Chip Id error. Image Chip Id = %04x, Board Chip Id = %04x.\n", tagChipId, chipId);
+ result = -1;
+ }
+
+ return result;
+}
+
+// return -1: fail.
+// 0: OK.
+int verifyTag( PFILE_TAG pTag, int verbose )
+{
+ UINT32 crc;
+ FLASH_ADDR_INFO info;
+ int tagVer, curVer;
+
+ kerSysFlashAddrInfoGet( &info );
+
+ tagVer = atoi(pTag->tagVersion);
+ curVer = atoi(BCM_TAG_VER);
+
+ if (tagVer != curVer)
+ {
+ if( verbose )
+ {
+ printf("Firmware tag version [%d] is not compatible with the current Tag version [%d].\n", \
+ tagVer, curVer);
+ }
+ return -1;
+ }
+
+ if (checkChipId(xtoi(pTag->chipId), pTag->signiture_2) != 0)
+ return -1;
+
+ // check tag validate token first
+ crc = CRC32_INIT_VALUE;
+ crc = getCrc32((byte *) pTag, (UINT32)TAG_LEN-TOKEN_LEN, crc);
+
+ if (crc != (UINT32)(*(UINT32*)(pTag->tagValidationToken)))
+ {
+ if( verbose )
+ printf("Illegal image ! Tag crc failed.\n");
+ return -1;
+ }
+ return 0;
+}
+
+#if (INC_NAND_FLASH_DRIVER==0)
+PFILE_TAG getTagFromPartition(int imageNumber)
+{
+ static unsigned char sectAddr1[sizeof(FILE_TAG)];
+ static unsigned char sectAddr2[sizeof(FILE_TAG)];
+ int blk = 0;
+ UINT32 crc;
+ PFILE_TAG pTag = NULL;
+ unsigned char *pBase = flash_get_memptr(0);
+ unsigned char *pSectAddr = NULL;
+
+ /* The image tag for the first image is always after the boot loader.
+ * The image tag for the second image, if it exists, is at one half
+ * of the flash size.
+ */
+ if( imageNumber == 1 )
+ {
+
+ FLASH_ADDR_INFO flash_info;
+
+ kerSysFlashAddrInfoGet(&flash_info);
+ blk = flash_get_blk((int)(pBase+flash_info.flash_rootfs_start_offset));
+ pSectAddr = sectAddr1;
+ }
+ else
+ if( imageNumber == 2 )
+ {
+ blk = flash_get_blk((int) (pBase + (flash_get_total_size() / 2)));
+ pSectAddr = sectAddr2;
+ }
+
+ if( blk )
+ {
+ memset(pSectAddr, 0x00, sizeof(FILE_TAG));
+ flash_read_buf((unsigned short) blk, 0, pSectAddr, sizeof(FILE_TAG));
+ crc = CRC32_INIT_VALUE;
+ crc = getCrc32(pSectAddr, (UINT32)TAG_LEN-TOKEN_LEN, crc);
+ pTag = (PFILE_TAG) pSectAddr;
+ if (crc != (UINT32)(*(UINT32*)(pTag->tagValidationToken)))
+ pTag = NULL;
+ }
+
+ return( pTag );
+}
+#else
+#define tag_not_searched 0
+#define tag_not_found 1
+#define tag_found 2
+PFILE_TAG getTagFromPartition(int imageNumber)
+{
+ extern unsigned char *mem_topofmem;
+ static FILE_TAG Tag1 = {{tag_not_searched}};
+ static FILE_TAG Tag2 = {{tag_not_searched}};
+ PFILE_TAG pTag = (imageNumber == 2) ? &Tag2 : &Tag1;
+ PFILE_TAG ret = NULL;
+
+ switch( pTag->tagVersion[0] )
+ {
+ case tag_not_searched:
+ {
+ int rootfs = (imageNumber == 2) ? NP_ROOTFS_2 : NP_ROOTFS_1;
+ char fname[] = NAND_CFE_RAM_NAME;
+ int fname_actual_len = strlen(fname);
+ int fname_cmp_len = strlen(fname) - 3; /* last three are digits */
+ unsigned char *buf = (unsigned char *) mem_topofmem + 1024;
+ unsigned char *p;
+ int len = flash_get_sector_size(0);
+ int num_blks = flash_get_numsectors();
+ int i, done, start_blk, end_blk;
+ struct jffs2_raw_dirent *pdir;
+ unsigned long version = 0;
+ NVRAM_DATA nvramData;
+
+ pTag->tagVersion[0] = tag_not_found;
+ readNvramData(&nvramData);
+ validateNandPartTbl(&nvramData);
+
+ if( nvramData.ulNandPartOfsKb[rootfs] > 0 &&
+ nvramData.ulNandPartOfsKb[rootfs] < ((num_blks * len) / 1024) &&
+ nvramData.ulNandPartSizeKb[rootfs] > 0 &&
+ nvramData.ulNandPartSizeKb[rootfs] < ((num_blks * len) / 1024) )
+ {
+ const int max_not_jffs2 = 10;
+ int not_jffs2 = 0;
+
+ start_blk = nvramData.ulNandPartOfsKb[rootfs] / (len / 1024);
+ end_blk =
+ start_blk + (nvramData.ulNandPartSizeKb[rootfs] / (len / 1024));
+
+ /* Find the directory entry. */
+ for( i = start_blk, done = 0; i < end_blk && done == 0; i++ )
+ {
+ if( flash_read_buf(i, 0, buf, len) > 0 )
+ {
+ p = buf;
+ while( p < buf + len )
+ {
+ pdir = (struct jffs2_raw_dirent *) p;
+ if( je16_to_cpu(pdir->magic) == JFFS2_MAGIC_BITMASK )
+ {
+ if( je16_to_cpu(pdir->nodetype) ==
+ JFFS2_NODETYPE_DIRENT &&
+ fname_actual_len == pdir->nsize &&
+ !memcmp(fname, pdir->name, fname_cmp_len) )
+ {
+ if( je32_to_cpu(pdir->version) > version )
+ {
+ if( je32_to_cpu(pdir->ino) != 0 )
+ {
+ unsigned char *seq =
+ pdir->name + fname_cmp_len;
+ pTag->imageSequence[0] = seq[0];
+ pTag->imageSequence[1] = seq[1];
+ pTag->imageSequence[2] = seq[2];
+ pTag->imageSequence[3] = '\0';
+ pTag->tagVersion[0] = tag_found;
+
+ version = je32_to_cpu(pdir->version);
+
+ /* Setting 'done = 1' assumes there is
+ * only one version of the directory
+ * entry.
+ */
+ done = 1;
+ ret = pTag;
+ break;
+ }
+ }
+ }
+
+ p += (je32_to_cpu(pdir->totlen) + 0x03) & ~0x03;
+ not_jffs2 = 0;
+ }
+ else
+ {
+ if( not_jffs2++ > max_not_jffs2 )
+ done = 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case tag_found:
+ ret = pTag;
+ break;
+
+ case tag_not_found:
+ ret = NULL;
+ break;
+ }
+
+ return(ret);
+}
+#endif
+
+
+int getPartitionFromTag( PFILE_TAG pTag )
+{
+ int ret = 0;
+
+ if( pTag )
+ {
+ PFILE_TAG pTag1 = getTagFromPartition(1);
+ PFILE_TAG pTag2 = getTagFromPartition(2);
+ int sequence = atoi(pTag->imageSequence);
+ int sequence1 = (pTag1) ? atoi(pTag1->imageSequence) : -1;
+ int sequence2 = (pTag2) ? atoi(pTag2->imageSequence) : -1;
+
+ if( pTag1 && sequence == sequence1 )
+ ret = 1;
+ else
+ if( pTag2 && sequence == sequence2 )
+ ret = 2;
+ }
+
+ return( ret );
+}
+
+PFILE_TAG getBootImageTag(void)
+{
+ PFILE_TAG pTag = NULL;
+
+ if( flash_get_flash_type() != FLASH_IFC_NAND )
+ {
+ PFILE_TAG pTag1 = getTagFromPartition(1);
+
+ /* Foxconn modified end pling 10/13/2008 */
+ PFILE_TAG pTag2 = NULL;
+ // PFILE_TAG pTag2 = getTagFromPartition(2);
+ //* Foxconn modified end pling 10/13/2008 */
+
+ if( pTag1 && pTag2 )
+ {
+ /* Two images are flashed. */
+ int sequence1 = atoi(pTag1->imageSequence);
+ int sequence2 = atoi(pTag2->imageSequence);
+
+ if( bootInfo.bootPartition == BOOT_LATEST_IMAGE )
+ pTag = (sequence2 > sequence1) ? pTag2 : pTag1;
+ else /* Boot from the previous image. */
+ pTag = (sequence2 < sequence1) ? pTag2 : pTag1;
+ }
+ else
+ /* One image is flashed. */
+ pTag = (pTag2) ? pTag2 : pTag1;
+ }
+ else
+ {
+ /* TBD. Verify that linux is on the file system. */
+ /* pTag pointer is only compared to NULL for NAND flash boot. */
+ pTag = (PFILE_TAG) 1;
+ }
+
+ return( pTag );
+}
+
+static void UpdateImageSequenceNumber( char *imageSequence )
+{
+ int newImageSequence = 0;
+ PFILE_TAG pTag = getTagFromPartition(1);
+
+ if( pTag )
+ newImageSequence = atoi(pTag->imageSequence);
+
+ pTag = getTagFromPartition(2);
+ if( pTag && atoi(pTag->imageSequence) > newImageSequence )
+ newImageSequence = atoi(pTag->imageSequence);
+
+ newImageSequence++;
+ sprintf(imageSequence, "%d", newImageSequence);
+}
+
+// return -1: fail.
+// 0: OK.
+int flashImage(uint8_t *imagePtr)
+{
+ UINT32 crc;
+ FLASH_ADDR_INFO info;
+ int totalImageSize = 0;
+ int cfeSize;
+ int cfeAddr, rootfsAddr, kernelAddr;
+ int status = 0;
+ PFILE_TAG pTag = (PFILE_TAG) imagePtr;
+ NVRAM_DATA nvramData, tmpNvramData;
+
+ if( flash_get_flash_type() == FLASH_IFC_NAND )
+ {
+ printf("ERROR: Image is not a valid NAND flash image.\n");
+ return -1;
+ }
+
+ // save existing NVRAM data into a local structure
+ readNvramData(&nvramData);
+
+ if( verifyTag( pTag, 1 ) == -1 )
+ return -1;
+
+ kerSysFlashAddrInfoGet( &info );
+
+ // check imageCrc
+ totalImageSize = atoi(pTag->totalImageLen);
+ crc = CRC32_INIT_VALUE;
+ crc = getCrc32((imagePtr+TAG_LEN), (UINT32) totalImageSize, crc);
+
+ if (crc != (UINT32) (*(UINT32*)(pTag->imageValidationToken)))
+ {
+ printf(" Illegal image ! Image crc failed.\n");
+ return -1;
+ }
+
+ cfeSize = cfeAddr = rootfsAddr = kernelAddr = 0;
+
+ // check cfe's existence
+ cfeAddr = atoi(pTag->cfeAddress);
+ if (cfeAddr)
+ {
+ cfeSize = atoi(pTag->cfeLen);
+ if( (cfeSize <= 0) )
+ {
+ printf("Illegal cfe size [%d].\n", cfeSize );
+ return -1;
+ }
+
+ printf("\nFlashing CFE: ");
+ if ((status = kerSysBcmImageSet(cfeAddr+BOOT_OFFSET, imagePtr+TAG_LEN,
+ cfeSize, 0)) != 0)
+ {
+ printf("Failed to flash CFE. Error: %d\n", status);
+ return status;
+ }
+
+ // Check if the new image has valid NVRAM
+ if ((readNvramData(&tmpNvramData) != 0) || (BpSetBoardId(tmpNvramData.szBoardId) != BP_SUCCESS) || (BpSetVoiceBoardId(tmpNvramData.szBoardId) != BP_SUCCESS))
+ writeNvramData(&nvramData);
+ }
+
+ // check root filesystem and kernel existence
+ rootfsAddr = atoi(pTag->rootfsAddress);
+ kernelAddr = atoi(pTag->kernelAddress);
+
+ if( rootfsAddr && kernelAddr )
+ {
+ char *p;
+ unsigned char *tagFs = imagePtr;
+ unsigned int baseAddr = (unsigned int) flash_get_memptr(0);
+ unsigned int totalSize = (unsigned int) flash_get_total_size();
+ unsigned int reservedBytesAtEnd;
+ unsigned int availableSizeOneImg;
+ unsigned int reserveForTwoImages;
+ unsigned int availableSizeTwoImgs;
+ unsigned int newImgSize = atoi(pTag->rootfsLen)+atoi(pTag->kernelLen);
+ PFILE_TAG pCurTag = getBootImageTag();
+ UINT32 crc;
+ unsigned int curImgSize = 0;
+ unsigned int rootfsOffset = (unsigned int)rootfsAddr-IMAGE_BASE-TAG_LEN;
+ FLASH_ADDR_INFO flash_info;
+
+ kerSysFlashAddrInfoGet(&flash_info);
+ if( rootfsOffset < flash_info.flash_rootfs_start_offset )
+ {
+ // Increase rootfs and kernel addresses by the difference between
+ // rootfs offset and what it needs to be.
+ rootfsAddr += flash_info.flash_rootfs_start_offset - rootfsOffset;
+ kernelAddr += flash_info.flash_rootfs_start_offset - rootfsOffset;
+ sprintf(pTag->rootfsAddress,"%lu", (unsigned long) rootfsAddr);
+ sprintf(pTag->kernelAddress,"%lu", (unsigned long) kernelAddr);
+ crc = CRC32_INIT_VALUE;
+ crc = getCrc32((unsigned char *)pTag,(UINT32)TAG_LEN-TOKEN_LEN,crc);
+ *(unsigned long *) &pTag->tagValidationToken[0] = crc;
+ }
+
+ rootfsAddr += BOOT_OFFSET;
+ kernelAddr += BOOT_OFFSET;
+
+ reservedBytesAtEnd = flash_get_reserved_bytes_at_end(&flash_info);
+ availableSizeOneImg = totalSize - ((unsigned int)rootfsAddr-baseAddr) -
+ reservedBytesAtEnd;
+ reserveForTwoImages =
+ (flash_info.flash_rootfs_start_offset > reservedBytesAtEnd)
+ ? flash_info.flash_rootfs_start_offset : reservedBytesAtEnd;
+ availableSizeTwoImgs = (totalSize / 2) - reserveForTwoImages;
+
+// printf("availableSizeOneImage=%dKB availableSizeTwoImgs=%dKB reserve=%dKB\n",
+// availableSizeOneImg/1024, availableSizeTwoImgs/1024, reserveForTwoImages/1024);
+
+ if( pCurTag )
+ curImgSize = atoi(pCurTag->rootfsLen) + atoi(pCurTag->kernelLen);
+
+ if( newImgSize > availableSizeOneImg)
+ {
+ printf("Illegal image size %d. Image size must not be greater "
+ "than %d.\n", newImgSize, availableSizeOneImg);
+ return -1;
+ }
+
+ // tag is alway at the sector start of fs
+ if (cfeAddr)
+ {
+ // will trash cfe memory, but cfe is already flashed
+ tagFs = imagePtr + cfeSize;
+ memcpy(tagFs, imagePtr, TAG_LEN);
+ }
+
+ // If the current image fits in half the flash space and the new
+ // image to flash also fits in half the flash space, then flash it
+ // in the partition that is not currently being used to boot from.
+ if( curImgSize <= availableSizeTwoImgs &&
+ newImgSize <= availableSizeTwoImgs &&
+ getPartitionFromTag( pCurTag ) == 1 )
+ {
+ // Update rootfsAddr to point to the second boot partition.
+ int offset = (totalSize / 2) + TAG_LEN;
+
+ sprintf(((PFILE_TAG) tagFs)->kernelAddress, "%lu",
+ (unsigned long) IMAGE_BASE + offset + (kernelAddr-rootfsAddr));
+ kernelAddr = baseAddr + offset + (kernelAddr - rootfsAddr);
+
+ sprintf(((PFILE_TAG) tagFs)->rootfsAddress, "%lu",
+ (unsigned long) IMAGE_BASE + offset);
+ rootfsAddr = baseAddr + offset;
+ }
+
+ UpdateImageSequenceNumber( ((PFILE_TAG) tagFs)->imageSequence );
+ crc = CRC32_INIT_VALUE;
+ crc = getCrc32((unsigned char *)tagFs, (UINT32)TAG_LEN-TOKEN_LEN, crc);
+ *(unsigned long *) &((PFILE_TAG) tagFs)->tagValidationToken[0] = crc;
+
+ printf("\nFlashing root file system and kernel at 0x%8.8lx: ",
+ rootfsAddr - TAG_LEN);
+ if( (status = kerSysBcmImageSet((rootfsAddr-TAG_LEN), tagFs,
+ TAG_LEN + newImgSize, 0)) != 0 )
+ {
+ printf("Failed to flash root file system. Error: %d\n", status);
+ return status;
+ }
+
+ for( p = nvramData.szBootline; p[2] != '\0'; p++ )
+ {
+ if( p[0] == 'p' && p[1] == '=' && p[2] != BOOT_LATEST_IMAGE )
+ {
+ // Change boot partition to boot from new image.
+ p[2] = BOOT_LATEST_IMAGE;
+ writeNvramData(&nvramData);
+ break;
+ }
+ }
+ }
+
+ printf(".\n*** Image flash done *** !\n");
+
+ return status;
+}
+
+static int nandUpdateImageSequenceNumber( uint8_t *imagePtr, int imageSize )
+{
+ unsigned char *buf, *p;
+ char fname[] = NAND_CFE_RAM_NAME;
+ int fname_actual_len = strlen(fname);
+ int fname_cmp_len = strlen(fname) - 3; /* last three are digits */
+ int len = flash_get_sector_size(0);
+ struct jffs2_raw_dirent *pdir;
+ unsigned long version = 0;
+ PFILE_TAG pTag1 = getTagFromPartition(1);
+ PFILE_TAG pTag2 = getTagFromPartition(2);
+ int seq = (pTag1) ? atoi(pTag1->imageSequence) : -1;
+ int seq2 = (pTag2) ? atoi(pTag2->imageSequence) : -1;
+ int ret = 0;
+
+ if( seq2 > seq )
+ seq = seq2;
+
+ if( seq != -1 )
+ {
+ int done = 0;
+
+ /* Increment the new highest sequence number. Add it to the CFE RAM
+ * file name.
+ */
+ seq++;
+
+ for(buf = imagePtr; buf < imagePtr+imageSize && done == 0; buf += len)
+ {
+ p = buf;
+ while( p < buf + len )
+ {
+ pdir = (struct jffs2_raw_dirent *) p;
+ if( je16_to_cpu(pdir->magic) == JFFS2_MAGIC_BITMASK )
+ {
+ if( je16_to_cpu(pdir->nodetype) == JFFS2_NODETYPE_DIRENT &&
+ fname_actual_len == pdir->nsize &&
+ !memcmp(fname, pdir->name, fname_cmp_len) &&
+ je32_to_cpu(pdir->version) > version &&
+ je32_to_cpu(pdir->ino) != 0 )
+ {
+ p = pdir->name + fname_cmp_len;
+ p[0] = (seq / 100) + '0';
+ p[1] = ((seq % 100) / 10) + '0';
+ p[2] = ((seq % 100) % 10) + '0';
+ p[3] = '\0';
+
+ je32_to_cpu(pdir->name_crc) = getCrc32(pdir->name,
+ (unsigned long) fname_actual_len, 0);
+
+ version = je32_to_cpu(pdir->version);
+
+ /* Setting 'done = 1' assumes there is only one version
+ * of the directory entry.
+ */
+ done = 1;
+ ret = (buf - imagePtr) / len; /* block number */
+ break;
+ }
+
+ p += (je32_to_cpu(pdir->totlen) + 0x03) & ~0x03;
+ }
+ else
+ break;
+ }
+ }
+ }
+
+ return(ret);
+}
+
+// return -1: fail.
+// 0: OK.
+int writeWholeImage(uint8_t *imagePtr, int wholeImageSize)
+{
+ UINT32 crc;
+ int status = 0;
+ int offset = 0;
+ int imageSize = wholeImageSize - TOKEN_LEN;
+ unsigned char crcBuf[CRC_LEN];
+ NVRAM_DATA nvramData, tmpNvramData;
+ WFI_TAG wfiTag;
+#if (INC_SPI_PROG_NAND==1)
+ if( flash_get_flash_type() != FLASH_IFC_NAND && wholeImageSize > FLASH_LENGTH_BOOT_ROM)
+ flash_change_flash_type(FLASH_IFC_NAND);
+#endif
+
+ // if whole image size (plus TOKEN_LEN of crc) is greater than total flash size, return error
+ if (wholeImageSize > (flash_get_total_size() + TOKEN_LEN))
+ {
+ printf("Image size too big\n");
+ return -1;
+ }
+
+ memcpy(&wfiTag, imagePtr + imageSize, sizeof(wfiTag));
+ if( (wfiTag.wfiVersion & WFI_ANY_VERS_MASK) == WFI_ANY_VERS &&
+ checkChipId(wfiTag.wfiChipId, NULL) != 0 )
+ return -1;
+
+ // check tag validate token first
+ crc = CRC32_INIT_VALUE;
+ crc = getCrc32(imagePtr, (UINT32)imageSize, crc);
+ memcpy(crcBuf, imagePtr+imageSize, CRC_LEN);
+ if (memcmp(&crc, crcBuf, CRC_LEN) != 0)
+ {
+ printf("Illegal whole flash image\n");
+ return -1;
+ }
+
+ // save existing NVRAM data into a local structure
+ readNvramData(&nvramData);
+
+ if( flash_get_flash_type() == FLASH_IFC_NAND )
+ {
+ /* The CFE ROM boot loader saved the rootfs partition index at the
+ * memory location before CFE RAM load address.
+ */
+ extern unsigned char _ftext;
+
+ /* Allow addition blocks to flash cfram block that has sequence number
+ * and is flashed last.
+ */
+ const int overhead_blocks = 8;
+
+ int rootfs = (int) *(&_ftext - 1);
+ int blksize = flash_get_sector_size(0) / 1024;
+ int sectsize = flash_get_sector_size(0);
+ int i, cferam_blk, after_cferam, cferam_overhead;
+
+ if( (wfiTag.wfiVersion & WFI_ANY_VERS_MASK) == WFI_ANY_VERS &&
+ ((blksize == 16 && wfiTag.wfiFlashType != WFI_NAND16_FLASH) ||
+ (blksize == 128 && wfiTag.wfiFlashType != WFI_NAND128_FLASH)) )
+ {
+ printf("\nERROR: NAND flash block size does not match image "
+ "block size\n\n");
+ return -1;
+ }
+
+ if( *(unsigned short *) imagePtr != JFFS2_MAGIC_BITMASK )
+ {
+ /* Flash block 0 (cferom). */
+ PNVRAM_DATA pnd = (PNVRAM_DATA) (imagePtr + NVRAM_DATA_OFFSET);
+ char *p;
+
+ /* Copy NVRAM data to block to be flashed so it is preserved. */
+ memcpy((unsigned char *) pnd, (unsigned char *) &nvramData,
+ sizeof(NVRAM_DATA));
+ for( p = pnd->szBootline; p[2] != '\0'; p++ )
+ {
+ if( p[0] == 'p' && p[1] == '=' && p[2] != BOOT_LATEST_IMAGE )
+ {
+ // Change boot partition to boot from new image.
+ p[2] = BOOT_LATEST_IMAGE;
+ break;
+ }
+ }
+
+ /* Recalculate the nvramData CRC. */
+ pnd->ulCheckSum = 0;
+ pnd->ulCheckSum = getCrc32((unsigned char *) pnd,
+ sizeof(NVRAM_DATA), CRC32_INIT_VALUE);
+
+ if((status = kerSysBcmImageSet(FLASH_BASE,imagePtr,sectsize,0)) != 0)
+ printf("Failed to flash block 0. Error: %d\n", status);
+ imagePtr += sectsize;
+ imageSize -= sectsize;
+ }
+
+ validateNandPartTbl(&nvramData);
+ cferam_blk = nandUpdateImageSequenceNumber(imagePtr, imageSize);
+
+ /* rootfs is the partition that the CFE RAM booted from. Write the
+ * image to the other rootfs partition.
+ */
+ if(rootfs == NP_ROOTFS_1 && nvramData.ulNandPartSizeKb[NP_ROOTFS_2]>0)
+ offset = nvramData.ulNandPartOfsKb[NP_ROOTFS_2] * 1024;
+ else
+ offset = nvramData.ulNandPartOfsKb[NP_ROOTFS_1] * 1024;
+
+ after_cferam = (cferam_blk + 1) * sectsize;
+ cferam_overhead = overhead_blocks * sectsize;
+
+ /* Erase block with cferam JFFS2 directory entry so if flashing this
+ * image does not finish, the partition will not be valid.
+ */
+ for( i = 0; i < (cferam_blk + 1 + overhead_blocks); i++ )
+ flash_sector_erase_int((offset / sectsize) + i);
+
+ /* Flash image after cferam directory entry. */
+ printf("\nFlashing root file system at 0x%8.8lx: ", FLASH_BASE+offset);
+ if((status = kerSysBcmImageSet(FLASH_BASE + offset + after_cferam +
+ cferam_overhead, imagePtr + after_cferam, imageSize - after_cferam,
+ 1)) != 0)
+ {
+ printf("Failed to flash whole image. Error: %d\n", status);
+ return status;
+ }
+
+ /* Flash block(s) up to and including the block with cferam JFFS2
+ * directory entry.
+ */
+ if((status = kerSysBcmImageSet(FLASH_BASE + offset, imagePtr,
+ after_cferam, 0)) != 0)
+ {
+ printf("Failed to flash whole image. Error: %d\n", status);
+ return status;
+ }
+ }
+ else /* NOR FLASH */
+ {
+ printf("\nFlashing root file system and kernel at 0x%8.8lx\n",
+ FLASH_BASE+offset);
+
+ if( (wfiTag.wfiVersion & WFI_ANY_VERS_MASK) == WFI_ANY_VERS &&
+ wfiTag.wfiFlashType != WFI_NOR_FLASH )
+ {
+ printf("\nERROR: Image does not support a NOR flash device.\n\n");
+ return -1;
+ }
+
+ if((status = kerSysBcmImageSet(FLASH_BASE+offset, imagePtr, imageSize,
+ 1)) != 0)
+ {
+ printf("Failed to flash whole image. Error: %d\n", status);
+ return status;
+ }
+ }
+
+ // Check if the new image has valid NVRAM
+ // Also check if the new image still supports currently configured board ID
+ if( (readNvramData(&tmpNvramData) != 0) ||
+ (BpSetBoardId(tmpNvramData.szBoardId) != BP_SUCCESS) ||
+ (BpSetVoiceBoardId(tmpNvramData.szVoiceBoardId) != BP_SUCCESS) )
+ {
+ // Don't write NVRAM area if we are flashing tiny bridge image.
+ // unlike cfe.w, the tiny bridge .w image will not have NVRAM_DATA_ID set
+ if (*(unsigned long *) &tmpNvramData == NVRAM_DATA_ID)
+ writeNvramData(&nvramData);
+ }
+
+ return status;
+}
+
+int processPrompt(PPARAMETER_SETTING promptPtr, int promptCt)
+{
+ char tmpBuf[MAX_PROMPT_LEN];
+ int i = 0;
+ int bChange = FALSE;
+
+ printf("Press: <enter> to use current value\r\n");
+ printf(" '-' to go previous parameter\r\n");
+ printf(" '.' to clear the current value\r\n");
+ printf(" 'x' to exit this command\r\n");
+
+ memset(tmpBuf, 0, MAX_PROMPT_LEN);
+ while (i < promptCt)
+ {
+ if( (promptPtr+i)->enabled == FALSE )
+ {
+ if( tmpBuf[0] == '-' )
+ {
+ if( i > 0 )
+ {
+ i--;
+ continue;
+ }
+ }
+ else
+ {
+ i++;
+ continue;
+ }
+ }
+
+ if (strlen((promptPtr+i)->parameter) > 0)
+ printf("%s %s ", (promptPtr+i)->promptName, (promptPtr+i)->parameter);
+ else
+ printf("%s %s", (promptPtr+i)->promptName, (promptPtr+i)->parameter);
+
+ memset(tmpBuf, 0, MAX_PROMPT_LEN);
+ console_readline ("", tmpBuf, (promptPtr+i)->maxValueLength + 1);
+
+ switch (tmpBuf[0])
+ {
+ case '-': // go back one parameter
+ if (i > 0)
+ i--;
+ break;
+ case 'x': // get out the b command
+ if ((promptPtr+i)->func != 0) // validate function is supplied, do a check
+ {
+ if ((promptPtr+i)->func((promptPtr+i)->parameter))
+ {
+ printf("\n%s; Try again!\n", (promptPtr+i)->errorPrompt);
+ break;
+ }
+ }
+ i = promptCt;
+ break;
+ case '.': // clear the current parameter and advance
+ if ((promptPtr+i)->func != 0) // validate function is supplied, do a check
+ {
+ if ((promptPtr+i)->func(""))
+ {
+ printf("\n%s; Try again!\n", (promptPtr+i)->errorPrompt);
+ break;
+ }
+ }
+ memset((promptPtr+i)->parameter, 0, MAX_PROMPT_LEN);
+ i++;
+ bChange = TRUE;
+ break;
+ case 0: // no input; use default if it is OK
+ if ((promptPtr+i)->func != 0) // validate function is supplied, do a check
+ {
+ if ((promptPtr+i)->func((promptPtr+i)->parameter))
+ {
+ printf("\n%s; Try again!\n", (promptPtr+i)->errorPrompt);
+ break;
+ }
+ }
+ i++;
+ break;
+ default: // new parameter
+ if ((promptPtr+i)->func != 0) // validate function is supplied, do a check
+ {
+ if ((promptPtr+i)->func(tmpBuf))
+ {
+ printf("\n%s; Try again!\n", (promptPtr+i)->errorPrompt);
+ break;
+ }
+ }
+ memset((promptPtr+i)->parameter, 0, MAX_PROMPT_LEN);
+ memcpy((promptPtr+i)->parameter, tmpBuf, strlen(tmpBuf));
+ i++;
+ bChange = TRUE;
+ }
+ }
+
+ return bChange;
+
+} // processPrompt
+
+// write the nvramData struct to nvram after CRC is calculated
+void writeNvramData(PNVRAM_DATA pNvramData)
+{
+ UINT32 crc = CRC32_INIT_VALUE;
+
+ pNvramData->ulCheckSum = 0;
+ crc = getCrc32((unsigned char *)pNvramData, sizeof(NVRAM_DATA), crc);
+ pNvramData->ulCheckSum = crc;
+ kerSysNvRamSet((unsigned char *)pNvramData, sizeof(NVRAM_DATA), 0);
+}
+
+// read the nvramData struct from nvram
+// return -1: crc fail, 0 ok
+int readNvramData(PNVRAM_DATA pNvramData)
+{
+ UINT32 crc = CRC32_INIT_VALUE, savedCrc;
+
+ kerSysNvRamGet((unsigned char *)pNvramData, sizeof(NVRAM_DATA), 0);
+ savedCrc = pNvramData->ulCheckSum;
+ pNvramData->ulCheckSum = 0;
+ crc = getCrc32((unsigned char *)pNvramData, sizeof(NVRAM_DATA), crc);
+ if (savedCrc != crc)
+ return -1;
+
+ return 0;
+}
+
+static void convertBootInfo(void)
+{
+ char *x;
+
+ memset(&bootInfo, 0, sizeof(BOOT_INFO));
+ strcpy(bootInfo.boardIp, gBootParam[PARAM_IDX_BOARD_IPADDR].parameter);
+
+ if ((x = strchr(bootInfo.boardIp, ':'))) // has mask
+ {
+ *x = '\0';
+ convertMaskStr((x+1), bootInfo.boardMask);
+ }
+ strcpy(bootInfo.hostIp, gBootParam[PARAM_IDX_HOST_IPADDR].parameter);
+ if ((x = strchr(bootInfo.hostIp, ':'))) // ignore host mask
+ *x = '\0';
+ strcpy(bootInfo.gatewayIp, gBootParam[PARAM_IDX_GW_IPADDR].parameter);
+ if ((x = strchr(bootInfo.gatewayIp, ':'))) // ignore gw mask
+ *x = '\0';
+ bootInfo.runFrom = gBootParam[PARAM_IDX_RUN_FROM].parameter[0];
+ strcpy(bootInfo.hostFileName, gBootParam[PARAM_IDX_RUN_FILENAME].parameter);
+ strcpy(bootInfo.flashFileName, gBootParam[PARAM_IDX_FLASH_FILENAME].parameter);
+ bootInfo.bootDelay = (int)(gBootParam[PARAM_IDX_BOOT_DELAY].parameter[0] - '0');
+ bootInfo.bootPartition = gBootParam[PARAM_IDX_BOOT_IMAGE].parameter[0];
+}
+
+void getBootLine(void)
+{
+ int i;
+ char *curPtr;
+ char *dPtr;
+ NVRAM_DATA nvramData;
+
+ readNvramData(&nvramData);
+
+ if ((nvramData.szBootline[0] == (char)0xff) ||
+ (nvramData.szBootline[0] == (char)0))
+ {
+ setDefaultBootline();
+ return;
+ }
+
+ curPtr = nvramData.szBootline;
+ for (i = 0; (i < gNumBootParams) && (curPtr != 0); i++)
+ {
+ curPtr = strchr(curPtr, '=');
+ if (curPtr) // found '=' and get the param.
+ {
+ dPtr = strchr(curPtr, ' '); // find param. deliminator ' '
+ memset(gBootParam[i].parameter, 0, MAX_PROMPT_LEN);
+ memcpy(gBootParam[i].parameter, curPtr+1, dPtr-curPtr-1);
+ // move to next param.
+ curPtr = dPtr;
+ }
+ } // for loop
+
+ if (i < gNumBootParams) {
+ setDefaultBootline();
+ return;
+ }
+
+ convertBootInfo();
+}
+
+// print the bootline and board parameter info and fill in the struct for later use
+//
+int printSysInfo(void)
+{
+ int i;
+ ETHERNET_MAC_INFO EnetInfos[BP_MAX_ENET_MACS];
+
+ // display the bootline info
+
+ if( getTagFromPartition(1) == NULL || getTagFromPartition(2) == NULL )
+ gBootParam[PARAM_IDX_BOOT_IMAGE].enabled = FALSE;
+
+ for (i = 0; i < gNumBootParams; i++)
+ if( gBootParam[i].enabled )
+ printf("%s %s \n", gBootParam[i].promptName, gBootParam[i].parameter);
+
+ // display the board param
+ displayBoardParam();
+
+ if( BpGetEthernetMacInfo( EnetInfos, BP_MAX_ENET_MACS ) == BP_SUCCESS )
+ {
+ // Here we should print whether EMAC1 or EMAC2 is selected
+ }
+
+ printf("\n");
+
+ return 0;
+}
+
+
+//**************************************************************************
+// Function Name: changeBootLine
+// Description : Use vxWorks bootrom style parameter input method:
+// Press <enter> to use default, '-' to go to previous parameter
+// Note: Parameter is set to current value in the menu.
+// Returns : None.
+//**************************************************************************
+int changeBootLine(void)
+{
+ int i;
+ char boardIpSaved[BOOT_IP_LEN];
+ NVRAM_DATA nvramData;
+
+ readNvramData(&nvramData);
+
+ strcpy(boardIpSaved, bootInfo.boardIp);
+
+ if (processPrompt(gBootParam, gNumBootParams))
+ {
+ char *blPtr = nvramData.szBootline;
+ int paramLen;
+
+ memset(blPtr, 0, NVRAM_BOOTLINE_LEN);
+ for (i = 0; i < gNumBootParams; i++)
+ {
+ memcpy(blPtr, gBootParam[i].promptDefine, PROMPT_DEFINE_LEN);
+ blPtr += PROMPT_DEFINE_LEN;
+ paramLen = strlen(gBootParam[i].parameter);
+ memcpy(blPtr, gBootParam[i].parameter, paramLen);
+ blPtr += paramLen;
+ if (!(gBootParam[i].parameter[0] == ' '))
+ {
+ memcpy(blPtr, " ", 1);
+ blPtr += 1;
+ }
+ }
+ writeNvramData(&nvramData);
+ }
+
+ getBootLine();
+
+ // if board ip differs, do enet init
+ if (strcmp(boardIpSaved, bootInfo.boardIp) != 0)
+ enet_init();
+
+ return 0;
+
+}
+
+void setDefaultBootline(void)
+{
+ char boardIpSaved[BOOT_IP_LEN];
+ NVRAM_DATA nvramData;
+
+ readNvramData(&nvramData);
+ strcpy(boardIpSaved, bootInfo.boardIp);
+
+ memset(nvramData.szBootline, 0, NVRAM_BOOTLINE_LEN);
+ strncpy(nvramData.szBootline, DEFAULT_BOOTLINE, strlen(DEFAULT_BOOTLINE));
+ printf("Use default boot line parameters: %s\n", DEFAULT_BOOTLINE);
+ writeNvramData(&nvramData);
+
+ getBootLine();
+
+ // if board ip differs, do enet init
+ if (strcmp(boardIpSaved, bootInfo.boardIp) != 0)
+ enet_init();
+}
+
+//**************************************************************************
+// Function Name: changeAfeId
+// Description : Use vxWorks bootrom style parameter input method:
+// Press <enter> to use default, '-' to go to previous parameter
+// Note: Parameter is set to current value in the menu.
+// Returns : None.
+//**************************************************************************
+static void hex2Str(unsigned long num, char *str)
+{
+ static const char hextable[16] = "0123456789ABCDEF";
+ unsigned long i, n;
+ str[0] = '0';
+ str[1] = 'x';
+ if (0 == num) {
+ str[2] = '0';
+ str[3] = 0;
+ return;
+ }
+ str +=2;
+ n = num >> 28;
+ i = 0;
+ while (0 == n) {
+ num <<= 4;
+ n = num >> 28;
+ i++;
+ }
+ for (; i < 8; i++) {
+ *str++ = hextable[num >> 28];
+ num <<= 4;
+ }
+ *str = 0;
+}
+
+int changeAfeId(void)
+{
+ NVRAM_DATA nvramData;
+
+ readNvramData(&nvramData);
+ hex2Str(nvramData.afeId[0], gAfeId[0].parameter);
+ hex2Str(nvramData.afeId[1], gAfeId[1].parameter);
+ if (processPrompt(gAfeId, gAfeIdParams))
+ {
+ nvramData.afeId[0] = lib_atoi(gAfeId[0].parameter);
+ nvramData.afeId[1] = lib_atoi(gAfeId[1].parameter);
+ writeNvramData(&nvramData);
+ }
+ return 0;
+}
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_eth.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_eth.c
new file mode 100755
index 0000000..c4ea465
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_eth.c
@@ -0,0 +1,547 @@
+/*
+<:copyright-broadcom
+
+ Copyright (c) 2002 Broadcom Corporation
+ All Rights Reserved
+ No portions of this material may be reproduced in any form without the
+ written permission of:
+ Broadcom Corporation
+ 16215 Alton Parkway
+ Irvine, California 92619
+ All information contained in this document is Broadcom Corporation
+ company private, proprietary, and trade secret.
+
+:>
+*/
+
+/** Includes. **/
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_ioctl.h"
+#include "cfe_device.h"
+#include "cfe_devfuncs.h"
+#include "sbmips.h"
+#include "cfe_timer.h"
+#include "dev_bcm63xx_eth.h"
+#include "dev_bcm63xx_flash.h"
+#include "mii.h"
+#include "robosw_reg.h"
+
+#define DMA_RX_CHAN (softc->dmaPort * 2)
+#define DMA_TX_CHAN (softc->dmaPort * 2 + 1)
+
+#define CACHE_ALIGN 16
+extern void _cfe_flushcache(int, uint8_t *, uint8_t *);
+#define INVAL_RANGE(s,l) _cfe_flushcache(CFE_CACHE_INVAL_RANGE,((uint8_t *) (s)),((uint8_t *) (s))+(l))
+#define FLUSH_RANGE(s,l) _cfe_flushcache(CFE_CACHE_FLUSH_RANGE,((uint8_t *) (s)),((uint8_t *) (s))+(l))
+
+/** Externs. **/
+extern unsigned long sysGetEnetModeFlag(void);
+
+/** Prototypes. **/
+static void bcm63xx_ether_probe( cfe_driver_t * drv, unsigned long probe_a,
+ unsigned long probe_b, void * probe_ptr );
+static int bcm63xx_ether_open(cfe_devctx_t *ctx);
+static int bcm63xx_ether_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int bcm63xx_ether_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int bcm63xx_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int bcm63xx_ether_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int bcm63xx_ether_close(cfe_devctx_t *ctx);
+static int internal_open(bcmenet_softc * softc);
+
+/** Variables. **/
+const static cfe_devdisp_t bcm63xx_ether_dispatch = {
+ bcm63xx_ether_open,
+ bcm63xx_ether_read,
+ bcm63xx_ether_inpstat,
+ bcm63xx_ether_write,
+ bcm63xx_ether_ioctl,
+ bcm63xx_ether_close,
+ NULL,
+ NULL
+};
+
+const cfe_driver_t bcm63xx_enet = {
+ "BCM63xx Ethernet",
+ "eth",
+ CFE_DEV_NETWORK,
+ &bcm63xx_ether_dispatch,
+ bcm63xx_ether_probe
+};
+
+/** Functions. **/
+static void bcm63xx_ether_probe( cfe_driver_t * drv, unsigned long probe_a,
+ unsigned long probe_b, void * probe_ptr )
+{
+ bcmenet_softc * softc;
+ char descr[100];
+
+ softc = (bcmenet_softc *) KMALLOC( sizeof(bcmenet_softc), CACHE_ALIGN );
+ if( softc == NULL ) {
+ xprintf( "BCM63xx : Failed to allocate softc memory.\n" );
+ } else {
+ memset( softc, 0, sizeof(bcmenet_softc) );
+
+ if (internal_open( softc ) == -1)
+ xprintf("Failed initializing enet hardware\n");
+ else
+ {
+ cfe_attach( drv, softc, NULL, descr );
+ }
+ }
+}
+
+static int bcm63xx_ether_open(cfe_devctx_t *ctx)
+{
+ /* FIXME -- See if this can be returned to its normal place. */
+ return 0;
+}
+
+/*
+ * init_dma: Initialize DMA control register
+ */
+static void init_dma(bcmenet_softc *softc)
+{
+ uint32 *StateRam;
+ int i;
+
+ /*
+ * clear State RAM
+ */
+ StateRam = (UINT32 *)&softc->dmaCtrl->stram.s[0];
+ for (i = 0; i < sizeof(DmaStateRam) / sizeof(UINT32) * NUM_PORTS * 2; i++)
+ StateRam[i] = 0;
+
+ /*
+ * initialize IUDMA controller register
+ */
+ softc->dmaCtrl->controller_cfg = DMA_FLOWC_CH1_EN;
+ softc->dmaCtrl->flowctl_ch1_thresh_lo = DMA_FC_THRESH_LO;
+ softc->dmaCtrl->flowctl_ch1_thresh_hi = DMA_FC_THRESH_HI;
+ softc->dmaCtrl->flowctl_ch1_alloc = 0;
+
+ // transmit
+ softc->txDma->cfg = 0; /* initialize first (will enable later) */
+ softc->txDma->maxBurst = DMA_MAX_BURST_LENGTH;
+ softc->txDma->intMask = 0; /* mask all ints */
+ /* clr any pending interrupts on channel */
+ softc->txDma->intStat = DMA_DONE|DMA_NO_DESC|DMA_BUFF_DONE;
+ softc->txDma->intMask = DMA_DONE;
+ softc->dmaCtrl->stram.s[DMA_TX_CHAN].baseDescPtr = (uint32)K1_TO_PHYS((uint32_t)(softc->txFirstBdPtr));
+
+ // receive
+ softc->rxDma->cfg = 0; // initialize first (will enable later)
+ softc->rxDma->maxBurst = DMA_MAX_BURST_LENGTH;
+ softc->rxDma->intMask = 0; /* mask all ints */
+ /* clr any pending interrupts on channel */
+ softc->rxDma->intStat = DMA_DONE|DMA_NO_DESC|DMA_BUFF_DONE;
+ softc->rxDma->intMask = DMA_DONE;
+ softc->dmaCtrl->stram.s[DMA_RX_CHAN].baseDescPtr = (uint32)K1_TO_PHYS((uint32_t)(softc->rxFirstBdPtr));
+}
+
+
+static int internal_open(bcmenet_softc * softc)
+{
+ int i;
+ void *p;
+
+ robosw_init();
+ softc->dmaCtrl = (DmaRegs *)(SWITCH_DMA_BASE);
+
+ softc->rxDma = &softc->dmaCtrl->chcfg[DMA_RX_CHAN];
+ softc->txDma = &softc->dmaCtrl->chcfg[DMA_TX_CHAN];
+
+ // If doing SW reboot in EPI the controller can still be active
+ softc->rxDma->cfg = 0;
+ softc->txDma->cfg = 0;
+ softc->dmaCtrl->controller_cfg &= ~DMA_MASTER_EN;
+
+ p = KMALLOC( NR_TX_BDS * sizeof(DmaDesc), CACHE_ALIGN );
+ if( p == NULL ) {
+ xprintf( "BCM63xx : Failed to allocate txBds memory.\n" );
+ return -1;
+ }
+ INVAL_RANGE(p, NR_TX_BDS * sizeof(DmaDesc));
+ softc->txBds = (DmaDesc *)K0_TO_K1((uint32) p);
+
+ p = KMALLOC( NR_RX_BDS * sizeof(DmaDesc), CACHE_ALIGN );
+ if( p== NULL ) {
+ xprintf( "BCM63xx : Failed to allocate rxBds memory.\n" );
+ KFREE( (void *)(softc->txBds) );
+ softc->txBds = NULL;
+ return -1;
+ }
+ INVAL_RANGE(p, NR_RX_BDS * sizeof(DmaDesc));
+ softc->rxBds = (DmaDesc *)K0_TO_K1((uint32) p);
+
+ softc->rxBuffers = (uint32_t)KMALLOC( NR_RX_BDS * ENET_BUF_SIZE, CACHE_ALIGN );
+ if( softc->rxBuffers == NULL ) {
+ xprintf( "BCM63xx : Failed to allocate RxBuffer memory.\n" );
+ KFREE( (void *)(softc->txBds) );
+ softc->txBds = NULL;
+ KFREE( (void *)(softc->rxBds) );
+ softc->rxBds = NULL;
+ return -1;
+ }
+ INVAL_RANGE(softc->rxBuffers, NR_RX_BDS * ENET_BUF_SIZE);
+
+ softc->txBuffers = (uint32_t)KMALLOC( NR_TX_BDS * ENET_BUF_SIZE, CACHE_ALIGN );
+ if( softc->txBuffers == NULL ) {
+ xprintf( "BCM63xx : Failed to allocate txBuffer memory.\n" );
+ KFREE( (void *)(softc->rxBuffers) );
+ softc->rxBuffers = NULL;
+ KFREE( (void *)(softc->txBds) );
+ softc->txBds = NULL;
+ KFREE( (void *)(softc->rxBds) );
+ softc->rxBds = NULL;
+ return -1;
+ }
+ INVAL_RANGE(softc->txBuffers, NR_TX_BDS * ENET_BUF_SIZE);
+
+ /* Init the Receive Buffer Descriptor Ring. */
+ softc->rxFirstBdPtr = softc->rxBdReadPtr = softc->rxBds;
+ softc->rxLastBdPtr = softc->rxBds + NR_RX_BDS - 1;
+
+ for(i = 0; i < NR_RX_BDS; i++) {
+ (softc->rxBds + i)->status = DMA_OWN;
+ (softc->rxBds + i)->length = ENET_BUF_SIZE;
+ (softc->rxBds + i)->address = softc->rxBuffers + i * ENET_BUF_SIZE;
+ (softc->rxBds + i)->address = K1_TO_PHYS( (softc->rxBds + i)->address );
+ softc->dmaCtrl->flowctl_ch1_alloc = 1;
+ }
+ softc->rxLastBdPtr->status |= DMA_WRAP;
+
+ /* Init Transmit Buffer Descriptor Ring. */
+ softc->txFirstBdPtr = softc->txNextBdPtr = softc->txBds;
+ softc->txLastBdPtr = softc->txBds + NR_TX_BDS - 1;
+
+ for(i = 0; i < NR_TX_BDS; i++) {
+ (softc->txBds + i)->status = 0;
+ (softc->txBds + i)->length = 0;
+ (softc->txBds + i)->address = softc->txBuffers + i * ENET_BUF_SIZE;
+ (softc->txBds + i)->address = K1_TO_PHYS( (softc->txBds + i)->address );
+ }
+ softc->txLastBdPtr->status = DMA_WRAP;
+
+ /* init dma registers */
+ init_dma(softc);
+
+ robosw_configure_ports();
+
+ softc->dmaCtrl->controller_cfg |= DMA_MASTER_EN;
+
+ softc->rxDma->cfg |= DMA_ENABLE;
+
+ softc->linkCheck = 0;
+
+ return 0;
+}
+
+static int bcm63xx_ether_read( cfe_devctx_t * ctx, iocb_buffer_t * buffer )
+{
+ unsigned char * dstptr;
+ unsigned char * srcptr;
+ volatile DmaDesc * CurrentBdPtr;
+ bcmenet_softc * softc = (bcmenet_softc *) ctx->dev_softc;
+ uint16 dmaFlag;
+
+ if( ctx == NULL ) {
+ xprintf( "No context\n" );
+ return -1;
+ }
+
+ if( buffer == NULL ) {
+ xprintf( "No dst buffer\n" );
+ return -1;
+ }
+
+ if( softc == NULL ) {
+ xprintf( "softc has not been initialized.\n" );
+ return -1;
+ }
+
+ dmaFlag = (uint16) softc->rxBdReadPtr->status;
+ if (!(dmaFlag & DMA_EOP))
+ {
+ xprintf("dmaFlag (return -1)[%04x]\n", dmaFlag);
+ return -1;
+ }
+
+ dstptr = buffer->buf_ptr;
+ CurrentBdPtr = softc->rxBdReadPtr;
+
+ srcptr = (unsigned char *)( PHYS_TO_K1(CurrentBdPtr->address) );
+
+ buffer->buf_retlen = ((CurrentBdPtr->length < buffer->buf_length) ? CurrentBdPtr->length : buffer->buf_length);
+
+ memcpy( dstptr, srcptr, buffer->buf_retlen );
+
+ CurrentBdPtr->length = ENET_BUF_SIZE;
+ CurrentBdPtr->status &= DMA_WRAP;
+ CurrentBdPtr->status |= DMA_OWN;
+
+ IncRxBdPtr( CurrentBdPtr, softc );
+ softc->rxBdReadPtr = CurrentBdPtr;
+ softc->dmaCtrl->flowctl_ch1_alloc = 1;
+
+ // enable rx dma
+ softc->rxDma->cfg = DMA_ENABLE;
+ return 0;
+}
+
+
+static int bcm63xx_ether_inpstat( cfe_devctx_t * ctx, iocb_inpstat_t * inpstat )
+{
+ bcmenet_softc * softc;
+ volatile DmaDesc * CurrentBdPtr;
+
+ /* ============================= ASSERTIONS ============================= */
+
+ if( ctx == NULL ) {
+ xprintf( "No context\n" );
+ return -1;
+ }
+
+ if( inpstat == NULL ) {
+ xprintf( "No inpstat buffer\n" );
+ return -1;
+ }
+
+ softc = (bcmenet_softc *)ctx->dev_softc;
+ if( softc == NULL ) {
+ xprintf( "softc has not been initialized.\n" );
+ return -1;
+ }
+
+ /* ====================================================================== */
+
+
+ CurrentBdPtr = softc->rxBdReadPtr;
+
+ // inp_status == 1 -> data available
+ inpstat->inp_status = (CurrentBdPtr->status & DMA_OWN) ? 0 : 1;
+
+ if (!inpstat->inp_status || (++softc->linkCheck > 100)) {
+ // Don't check link state too often when receiving data
+ softc->linkCheck = 0;
+ robosw_check_ports();
+ }
+
+ return 0;
+}
+
+
+static int bcm63xx_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ uint32_t status;
+ unsigned char * dstptr;
+ bcmenet_softc * softc;
+ volatile DmaDesc * CurrentBdPtr;
+ volatile uint32 txEvents = 0;
+
+ /* ============================= ASSERTIONS ============================= */
+
+ if( ctx == NULL ) {
+ xprintf( "No context\n" );
+ return -1;
+ }
+
+ if( buffer == NULL ) {
+ xprintf( "No dst buffer\n" );
+ return -1;
+ }
+
+ if( buffer->buf_length > ENET_MAX_MTU_SIZE ) {
+ xprintf( "src buffer too large.\n" );
+ xprintf( "size is %d\n", buffer->buf_length );
+ return -1;
+ }
+
+ softc = (bcmenet_softc *) ctx->dev_softc;
+ if( softc == NULL ) {
+ xprintf( "softc has not been initialized.\n" );
+ return -1;
+ }
+
+ /* ====================================================================== */
+
+ CurrentBdPtr = softc->txNextBdPtr;
+
+ /* Find out if the next BD is available. */
+ if( CurrentBdPtr->status & DMA_OWN ) {
+ xprintf( "No tx BD available ?!\n" );
+ return -1;
+ }
+
+ dstptr = (unsigned char *)PHYS_TO_K1( CurrentBdPtr->address );
+ memcpy( dstptr, buffer->buf_ptr, buffer->buf_length );
+
+ /* Set status of DMA BD to be transmitted. */
+ status = DMA_SOP | DMA_EOP | DMA_APPEND_CRC | DMA_OWN;
+ if( CurrentBdPtr == softc->txLastBdPtr ) {
+ status |= DMA_WRAP;
+ }
+
+ CurrentBdPtr->length = ((buffer->buf_length < ETH_ZLEN) ? ETH_ZLEN : buffer->buf_length);
+ CurrentBdPtr->status = status;
+
+ // Enable DMA for this channel
+ softc->txDma->cfg |= DMA_ENABLE;
+
+ // poll the dma status until done
+ do
+ {
+ txEvents = CurrentBdPtr->status;
+ } while (txEvents & DMA_OWN);
+
+
+ //Advance BD pointer to next in the chain.
+ InctxBdPtr( CurrentBdPtr, softc );
+ softc->txNextBdPtr = CurrentBdPtr;
+
+ return 0;
+}
+
+static int bcm63xx_ether_ioctl(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ bcmenet_softc *softc = (bcmenet_softc *) ctx->dev_softc;
+
+ switch ((int)buffer->buf_ioctlcmd) {
+ case IOCTL_ETHER_GETHWADDR:
+ memcpy(buffer->buf_ptr, softc->hwaddr, sizeof(softc->hwaddr));
+ return 0;
+
+ case IOCTL_ETHER_SETHWADDR:
+ memcpy(softc->hwaddr, buffer->buf_ptr, sizeof(softc->hwaddr));
+ return 0;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * bcm63xx_ether_flush: Flushes packets from the DMA receive ring
+ */
+static int bcm63xx_ether_flush(bcmenet_softc * softc)
+{
+ volatile DmaDesc * CurrentBdPtr;
+ uint16 dmaFlag;
+ unsigned char * srcptr;
+ uint16 len;
+ uint32 rxBdsCount = 0;
+ int i;
+
+ if( softc == NULL ) {
+ xprintf( "softc has not been initialized.\n" );
+ return -1;
+ }
+
+ xprintf("Disabling Switch ports.\n");
+
+ /* disable forwarding */
+ SWITCH->SwitchMode &= ~SwitchMode_FwdgEn;
+
+ /* Bring the link down on all switch ports */
+ for(i=0; i<8; ++i) {
+ SWITCH->PortOverride[i] &= ~PortOverride_Linkup;
+ /* disable Rx and Tx */
+ SWITCH->PortCtrl[i] = PortCtrl_DisableTx | PortCtrl_DisableRx;
+ }
+
+ for(i=0; i<1000; ++i) {
+ cfe_usleep(1000);
+ }
+
+ xprintf("Flushing Receive Buffers...\n");
+
+ while(!((dmaFlag = (uint16) softc->rxBdReadPtr->status) & DMA_OWN)) {
+
+ if (!(dmaFlag & DMA_EOP))
+ {
+ xprintf("dmaFlag (return -1)[%04x]\n", dmaFlag);
+ return -1;
+ }
+
+ CurrentBdPtr = softc->rxBdReadPtr;
+
+ srcptr = (unsigned char *)( PHYS_TO_K1(CurrentBdPtr->address) );
+
+ len = CurrentBdPtr->length;
+
+ ++rxBdsCount;
+
+ CurrentBdPtr->length = ENET_BUF_SIZE;
+ CurrentBdPtr->status &= DMA_WRAP;
+ CurrentBdPtr->status |= DMA_OWN;
+
+ IncRxBdPtr( CurrentBdPtr, softc );
+ softc->rxBdReadPtr = CurrentBdPtr;
+ softc->dmaCtrl->flowctl_ch1_alloc = 1;
+
+ // enable rx dma
+ softc->rxDma->cfg = DMA_ENABLE;
+ }
+
+ xprintf("%d buffers found.\n", rxBdsCount);
+
+ return 0;
+}
+
+static int bcm63xx_ether_close(cfe_devctx_t *ctx)
+{
+ int i;
+ bcmenet_softc * softc = (bcmenet_softc *) ctx->dev_softc;
+ unsigned long sts;
+
+ /* flush Rx DMA Channel */
+ bcm63xx_ether_flush(softc);
+
+ xprintf("Closing DMA Channels.\n");
+
+ sts = softc->rxDma->intStat;
+ softc->rxDma->intStat = sts;
+ softc->rxDma->intMask = 0;
+ softc->rxDma->cfg = 0;
+ // wait the current packet to complete before turning off EMAC, otherwise memory corruption can occur.
+ for(i=0; softc->rxDma->cfg & DMA_ENABLE; i++) {
+ // put the line below inside - it seems the signal can be lost and DMA never stops
+ softc->rxDma->cfg = 0;
+ if (i >= 20) {
+ xprintf("Rx Timeout !!!\n");
+ break;
+ }
+ cfe_usleep(100);
+ }
+
+ sts = softc->txDma->intStat;
+ softc->txDma->intStat = sts;
+ softc->txDma->intMask = 0;
+ softc->txDma->cfg = 0;
+ for(i=0; softc->txDma->cfg & DMA_ENABLE; i++) {
+ // put the line below inside - it seems the signal can be lost and DMA never stops
+ softc->txDma->cfg = 0;
+ if (i >= 20) {
+ xprintf("Tx Timeout !!!\n");
+ break;
+ }
+ cfe_usleep(100);
+ }
+
+ /* return buffer allocation register internal count to 0 */
+ softc->dmaCtrl->flowctl_ch1_alloc = (DMA_BUF_ALLOC_FORCE | 0);
+
+ softc->dmaCtrl->controller_cfg &= ~DMA_MASTER_EN;
+
+ KFREE( (void *)(softc->txBuffers) );
+ KFREE( (void *)(softc->rxBuffers) );
+ KFREE( (void *)(softc->txBds) );
+ KFREE( (void *)(softc->rxBds) );
+ return 0;
+}
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_flash.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_flash.c
new file mode 100755
index 0000000..cf38104
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_flash.c
@@ -0,0 +1,629 @@
+/***************************************************************************
+ * Broadcom Corp. Confidential
+ * Copyright 2001 Broadcom Corp. All Rights Reserved.
+ *
+ * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED
+ * SOFTWARE LICENSE AGREEMENT BETWEEN THE USER AND BROADCOM.
+ * YOU HAVE NO RIGHT TO USE OR EXPLOIT THIS MATERIAL EXCEPT
+ * SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
+ *
+ ***************************************************************************
+ * File Name : bcm63xx_flash.c
+ *
+ * Description: This file contains the flash device driver for bcm63xx board. Very similar to
+ * board.c in linux development.
+ *
+ * Created on : 4/18/2002 seanl
+ *
+ ***************************************************************************/
+
+
+/* Includes. */
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+
+#include "bcm_map.h"
+#include "bcm_hwdefs.h"
+#include "dev_bcm63xx_flash.h"
+#include "flash_api.h"
+#include "boardparms.h"
+#include "boardparms_voice.h"
+#include "bcm63xx_util.h"
+
+//#define DEBUG_FLASH
+
+/* This driver determines the NVRAM and persistent storage flash address and
+ * length.
+ */
+/* Foxconn start jenny add for timeout */
+extern int NMRPKeepAlive(void);
+extern int NMRPTFTPWaiting(void);
+extern int g_nmrp_keepalive;
+extern int nmrp_server_detected;
+/* Foxconn end jenny add for timeout*/
+
+static FLASH_ADDR_INFO fInfo;
+
+//**************************************************************************************
+// Flash read/write and image downloading..
+//**************************************************************************************
+
+void kerSysFlashInit( void )
+{
+ NVRAM_DATA nvramData;
+
+ flash_init();
+
+ while ((readNvramData(&nvramData) != 0) || (BpSetBoardId(nvramData.szBoardId) != BP_SUCCESS))
+ {
+ printf("\n*** Board is not initialized properly ***\n\n");
+ //setBoardParam(); /* Bob removed to set default board parameters, 11/01/2010 */
+ setDefaultBoardParam(); /* Bob added to set default board parameters, 11/01/2010 */
+ }
+
+ fInfo.flash_rootfs_start_offset = flash_get_sector_size(0);
+ if( fInfo.flash_rootfs_start_offset < FLASH_LENGTH_BOOT_ROM )
+ fInfo.flash_rootfs_start_offset = FLASH_LENGTH_BOOT_ROM;
+
+ flash_init_info(&nvramData, &fInfo);
+
+#if (INC_NAND_FLASH_DRIVER==1)
+ validateNandPartTbl(&nvramData);
+
+ /* Check if spare area data contains non 0xff values after JFFS2 clean
+ * marker. Early version of this CFE driver filled bytes 8 - 11 with
+ * 0 which Linux does not like.
+ */
+ {
+ extern int read_spare_data(int blk, unsigned char *buf, int bufsize);
+
+ int blk_size = flash_get_sector_size(0) / 1024;
+ int blk_start = nvramData.ulNandPartOfsKb[NP_DATA] / blk_size;
+ unsigned char spare[64];
+
+ memset(spare, 0xff, sizeof(spare));
+ if( read_spare_data(blk_start, spare, sizeof(spare)) == FLASH_API_OK )
+ {
+ const int spare_len = 8; /* Linux JFFS2 spare area is 8 bytes */
+ int i;
+
+ for( i = spare_len; i < sizeof(spare); i++ )
+ {
+ if( spare[i] != 0xff )
+ {
+ printf("Data spare area is not correct, erasing psi\n");
+ printf("%8.8lx %8.8lx %8.8lx %8.8lx\n",
+ *(unsigned long *) &spare[0],*(unsigned long *)&spare[4],
+ *(unsigned long *) &spare[8],*(unsigned long *)&spare[12]);
+ kerSysErasePsi();
+ break;
+ }
+ }
+ }
+ }
+#endif
+}
+
+#if (INC_NAND_FLASH_DRIVER==1) || (INC_SPI_PROG_NAND==1)
+/***********************************************************************
+ * Function Name: validateNandPartTbl
+ * Description : Checks the NAND partition table fields in NVRAM data.
+ * If nay of the fields are not valid, new values are set.
+ * Returns : None.
+ ***********************************************************************/
+void validateNandPartTbl(PNVRAM_DATA pNvramData)
+{
+ unsigned long ulBlockSizeKb = (unsigned long)flash_get_sector_size(0)/1024;
+ unsigned long ulTotalSizeKb = (unsigned long)flash_get_total_size() / 1024;
+
+#if (INC_SPI_PROG_NAND==1)
+ if( flash_get_flash_type() != FLASH_IFC_NAND )
+ return;
+#endif
+ if( pNvramData->ulNandPartSizeKb[NP_BOOT] != ulBlockSizeKb ||
+ pNvramData->ulNandPartSizeKb[NP_DATA] != NAND_DATA_SIZE_KB ||
+ (pNvramData->ulNandPartSizeKb[NP_BBT] != NAND_BBT_SMALL_SIZE_KB &&
+ pNvramData->ulNandPartSizeKb[NP_BBT] != NAND_BBT_BIG_SIZE_KB) )
+ {
+ /* Initialize NAND flash partition table. */
+ unsigned long ulRootfsSizeKb;
+ unsigned long ulBbtSizeKb = (ulTotalSizeKb > NAND_BBT_THRESHOLD_KB)
+ ? NAND_BBT_BIG_SIZE_KB : NAND_BBT_SMALL_SIZE_KB;
+
+ /* The Boot partition is first and is one block in size. */
+ pNvramData->ulNandPartOfsKb[NP_BOOT] = 0;
+ pNvramData->ulNandPartSizeKb[NP_BOOT] = ulBlockSizeKb;
+
+ /* The Bad Block Table partition is last and is a constant size. */
+ pNvramData->ulNandPartOfsKb[NP_BBT] = ulTotalSizeKb - ulBbtSizeKb;
+ pNvramData->ulNandPartSizeKb[NP_BBT] = ulBbtSizeKb;
+
+ /* The Data partition is before the BBT and is a constant size. */
+ pNvramData->ulNandPartOfsKb[NP_DATA] =
+ pNvramData->ulNandPartOfsKb[NP_BBT] - NAND_DATA_SIZE_KB;
+ pNvramData->ulNandPartSizeKb[NP_DATA] = NAND_DATA_SIZE_KB;
+
+ /* The first rootfs partition starts at the second sector. */
+ pNvramData->ulNandPartOfsKb[NP_ROOTFS_1] = ulBlockSizeKb;
+
+ /* The size of the two root file system partitions is whatever is left
+ * after the Boot, Data and BBT paritions divided by 2 and evenly
+ * divisible by the NAND flash block size.
+ */
+ ulRootfsSizeKb = ((pNvramData->ulNandPartOfsKb[NP_DATA] -
+ pNvramData->ulNandPartOfsKb[NP_ROOTFS_1]) / 2);
+ ulRootfsSizeKb = (ulRootfsSizeKb / ulBlockSizeKb) * ulBlockSizeKb;
+
+#if 1 /* support two file system partitions */
+ pNvramData->ulNandPartSizeKb[NP_ROOTFS_1] = ulRootfsSizeKb;
+
+ pNvramData->ulNandPartOfsKb[NP_ROOTFS_2] =
+ pNvramData->ulNandPartOfsKb[NP_ROOTFS_1] + ulRootfsSizeKb;
+ pNvramData->ulNandPartSizeKb[NP_ROOTFS_2] = ulRootfsSizeKb;
+#else /* support one file system partition */
+ pNvramData->ulNandPartSizeKb[NP_ROOTFS_1] = ulRootfsSizeKb * 2;
+
+ pNvramData->ulNandPartOfsKb[NP_ROOTFS_2] = ulTotalSizeKb;
+ pNvramData->ulNandPartSizeKb[NP_ROOTFS_2] = 0;
+#endif
+
+ writeNvramData(pNvramData);
+
+#if defined(DEBUG_FLASH)
+ printf("boot offset=0x%8.8lx, size=0x%8.8lx\n",
+ pNvramData->ulNandPartOfsKb[NP_BOOT],
+ pNvramData->ulNandPartSizeKb[NP_BOOT]);
+ printf("rootfs1 offset=0x%8.8lx, size=0x%8.8lx\n",
+ pNvramData->ulNandPartOfsKb[NP_ROOTFS_1],
+ pNvramData->ulNandPartSizeKb[NP_ROOTFS_1]);
+ printf("rootfs2 offset=0x%8.8lx, size=0x%8.8lx\n",
+ pNvramData->ulNandPartOfsKb[NP_ROOTFS_2],
+ pNvramData->ulNandPartSizeKb[NP_ROOTFS_2]);
+ printf("data offset=0x%8.8lx, size=0x%8.8lx\n",
+ pNvramData->ulNandPartOfsKb[NP_DATA],
+ pNvramData->ulNandPartSizeKb[NP_DATA]);
+ printf("bbt offset=0x%8.8lx, size=0x%8.8lx\n",
+ pNvramData->ulNandPartOfsKb[NP_BBT],
+ pNvramData->ulNandPartSizeKb[NP_BBT]);
+#endif
+ }
+}
+#else
+void validateNandPartTbl(PNVRAM_DATA pNvramData)
+{
+}
+#endif
+
+
+/***********************************************************************
+ * Function Name: kerSysFlashAddrInfoGet
+ * Description : Fills in a structure with information about the NVRAM
+ * and persistent storage sections of flash memory.
+ * Returns : None.
+ ***********************************************************************/
+void kerSysFlashAddrInfoGet(PFLASH_ADDR_INFO pflash_addr_info)
+{
+ memcpy(pflash_addr_info, &fInfo, sizeof(FLASH_ADDR_INFO));
+}
+
+// get shared blks into *** pTempBuf *** which has to be released bye the caller!
+// return: if pTempBuf != NULL, poits to the data with the dataSize of the buffer
+// !NULL -- ok
+// NULL -- fail
+static unsigned char *getSharedBlks(int start_blk, int num_blks)
+{
+ int i = 0;
+ int usedBlkSize = 0;
+ int sect_size = 0;
+ unsigned char *pTempBuf = NULL;
+ unsigned char *pBuf = NULL;
+
+ for (i = start_blk; i < (start_blk + num_blks); i++)
+ usedBlkSize += flash_get_sector_size((unsigned short) i);
+
+ if ((pTempBuf = (unsigned char *) KMALLOC(usedBlkSize, sizeof(long))) == NULL)
+ {
+ printf("failed to allocate memory with size: %d\n", usedBlkSize);
+ return pTempBuf;
+ }
+
+ pBuf = pTempBuf;
+ for (i = start_blk; i < (start_blk + num_blks); i++)
+ {
+ sect_size = flash_get_sector_size((unsigned short) i);
+#if defined(DEBUG_FLASH)
+ printf("getShareBlks: blk=%d, sect_size=%d\n", i, sect_size);
+#endif
+ flash_read_buf((unsigned short)i, 0, pBuf, sect_size);
+ pBuf += sect_size;
+ }
+
+ return pTempBuf;
+}
+
+
+
+// Set the pTempBuf to flash from start_blk for num_blks
+// return:
+// 0 -- ok
+// -1 -- fail
+static int setSharedBlks(int start_blk, int num_blks, unsigned char *pTempBuf)
+{
+ int i = 0;
+ int sect_size = 0;
+ int sts = 0;
+ unsigned char *pBuf = pTempBuf;
+
+ for (i = start_blk; i < (start_blk + num_blks); i++)
+ {
+ sect_size = flash_get_sector_size((unsigned short) i);
+ flash_sector_erase_int(i);
+ if (flash_write_buf(i, 0, pBuf, sect_size) != sect_size)
+ {
+ printf("Error writing flash sector %d.", i);
+ sts = -1;
+ break;
+ }
+
+#if defined(DEBUG_FLASH)
+ printf("setShareBlks: blk=%d, sect_size=%d\n", i, sect_size);
+#endif
+
+ pBuf += sect_size;
+ }
+
+ return sts;
+}
+
+
+
+/*******************************************************************************
+ * NVRAM functions
+ *******************************************************************************/
+
+// get nvram data
+// return:
+// 0 - ok
+// -1 - fail
+int kerSysNvRamGet(unsigned char *string, int strLen, int offset)
+{
+ unsigned char *pBuf = NULL;
+
+ if ((pBuf = getSharedBlks(NVRAM_SECTOR, 1)) == NULL)
+ return -1;
+
+ // get string off the memory buffer
+ memcpy(string, (pBuf + NVRAM_DATA_OFFSET + offset), strLen);
+
+ KFREE(pBuf);
+
+ return 0;
+}
+
+
+// set nvram
+// return:
+// 0 - ok
+// -1 - fail
+int kerSysNvRamSet(unsigned char *string, int strLen, int offset)
+{
+ int sts = 0;
+ unsigned char *pBuf = NULL;
+
+ if ((pBuf = getSharedBlks(NVRAM_SECTOR, 1)) == NULL)
+ return -1;
+
+ // set string to the memory buffer
+ memcpy((pBuf + NVRAM_DATA_OFFSET + offset), string, strLen);
+
+ if (setSharedBlks(NVRAM_SECTOR, 1, pBuf) != 0)
+ sts = -1;
+
+ KFREE(pBuf);
+
+ return sts;
+}
+
+/***********************************************************************
+ * Function Name: kerSysEraseNvRam
+ * Description : Erase the NVRAM storage section of flash memory.
+ * Returns : 1 -- ok, 0 -- fail
+ ***********************************************************************/
+int kerSysEraseNvRam(void)
+{
+ int sts = 1;
+ unsigned char *tempStorage = KMALLOC(NVRAM_LENGTH, sizeof(long));
+
+ // just write the whole buf with '0xff' to the flash
+ if (!tempStorage)
+ sts = 0;
+ else
+ {
+ memset(tempStorage, 0xff, NVRAM_LENGTH);
+ if (kerSysNvRamSet(tempStorage, NVRAM_LENGTH, 0) != 0)
+ sts = 0;
+ KFREE(tempStorage);
+ }
+
+ return sts;
+}
+
+
+/*******************************************************************************
+ * PSI functions
+ *******************************************************************************/
+
+#if (INC_NAND_FLASH_DRIVER!=1)
+/** set psi while preserving any other data that might be sharing sectors with
+ * the psi, e.g. scratch pad.
+ *
+ * @param string (IN) buffer that holds the data to be written.
+ * @param strLen (IN) length of buffer.
+ *
+ * @return 0 if OK, -1 on failure.
+ */
+static int kerSysPsiSet(const unsigned char *string, int strLen)
+{
+ int sts = 0;
+ unsigned char *pBuf = NULL;
+
+ if ((pBuf = getSharedBlks(fInfo.flash_persistent_start_blk,
+ fInfo.flash_persistent_number_blk)) == NULL)
+ return -1;
+
+ // set string to the memory buffer
+ memcpy((pBuf + fInfo.flash_persistent_blk_offset), string, strLen);
+
+ if (setSharedBlks(fInfo.flash_persistent_start_blk,
+ fInfo.flash_persistent_number_blk, pBuf) != 0)
+ sts = -1;
+
+ KFREE(pBuf);
+
+ return sts;
+}
+
+/** set backup psi
+ *
+ * Backup PSI does not share its sectors with anything else, so this
+ * function does not need to read first and write. Just write.
+ * This function expects the length of the buffer to be exactly the
+ * length of the entire PSI.
+ *
+ * @param string (IN) buffer that holds the data to be written.
+ *
+ * @return 0 if OK, -1 on failure.
+ */
+static int kerSysBackupPsiSet(const unsigned char *string)
+{
+ int sts = 0;
+
+ if (setSharedBlks(fInfo.flash_backup_psi_start_blk,
+ fInfo.flash_backup_psi_number_blk,
+ (unsigned char *) string) != 0)
+ sts = -1;
+
+ return sts;
+}
+
+/***********************************************************************
+ * Function Name: kerSysErasePsi
+ * Description : Erase the Psi storage section of flash memory.
+ * Returns : 1 -- ok, 0 -- fail
+ ***********************************************************************/
+int kerSysErasePsi(void)
+{
+ int sts = 1;
+ unsigned char *tempStorage;
+
+ if (fInfo.flash_persistent_start_blk == 0) {
+ sts = 0;
+ }
+ else {
+ tempStorage = KMALLOC(fInfo.flash_persistent_length, sizeof(long));
+ // just write the whole buf with '0xff' to the flash
+ if (!tempStorage)
+ sts = 0;
+ else
+ {
+ memset(tempStorage, 0xff, fInfo.flash_persistent_length);
+ if (kerSysPsiSet(tempStorage, fInfo.flash_persistent_length) != 0)
+ sts = 0;
+
+ // Also erase backup psi if it is there
+ if (fInfo.flash_backup_psi_number_blk > 0)
+ {
+ if (kerSysBackupPsiSet(tempStorage) != 0)
+ sts = 0;
+ }
+
+ KFREE(tempStorage);
+ }
+ }
+ return sts;
+}
+#else
+int kerSysErasePsi(void)
+{
+ int sts = 1;
+ NVRAM_DATA nvramData;
+
+ if( readNvramData(&nvramData) == 0 )
+ {
+ int blk_size = flash_get_sector_size(0) / 1024;
+ int blk_start = nvramData.ulNandPartOfsKb[NP_DATA] / blk_size;
+ int total_blks =
+ blk_start + (nvramData.ulNandPartSizeKb[NP_DATA]) / blk_size;
+
+ while( blk_start < total_blks )
+ {
+ flash_sector_erase_int(blk_start);
+ blk_start++;
+ }
+ sts = 0;
+ }
+
+ return(sts);
+}
+#endif
+
+// flash bcm image
+// return:
+// 0 - ok
+// !0 - the sector number fail to be flashed (should not be 0)
+int kerSysBcmImageSet( int flash_start_addr, unsigned char *string, int size, int fWholeImage)
+{
+ int sts;
+ int sect_size;
+ int blk_start;
+ // int savedSize = size;
+ int total_blks = flash_get_numsectors();
+
+ /* Foxconn add by Cliff Wang, 03/23/2010 */
+ unsigned char *pTempBuf = NULL;
+ int savedBlkStart;
+ /* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+ if( flash_get_flash_type() == FLASH_IFC_NAND )
+ {
+ if( flash_start_addr == FLASH_BASE )
+ total_blks = 1;
+ else
+ {
+ NVRAM_DATA nvramData;
+
+ if( readNvramData(&nvramData) == 0 )
+ {
+ sect_size = flash_get_sector_size(0);
+ int rootfs =
+ ((flash_start_addr - FLASH_BASE) / 1024 ==
+ nvramData.ulNandPartOfsKb[NP_ROOTFS_2])
+ ? NP_ROOTFS_2 : NP_ROOTFS_1;
+
+ total_blks = (nvramData.ulNandPartOfsKb[rootfs] +
+ nvramData.ulNandPartSizeKb[rootfs]) / (sect_size/ 1024);
+ }
+ }
+ }
+
+#if defined(DEBUG_FLASH)
+ printf("kerSysBcmImageSet: flash_start_addr=0x%x string=%p len=%d wholeImage=%d\n",
+ flash_start_addr, string, size, fWholeImage);
+#endif
+
+ blk_start = flash_get_blk(flash_start_addr);
+ /* Foxconn add start by Cliff Wang, 03/23/2010 */
+ savedBlkStart = blk_start;
+ if( blk_start < 0 )
+ return( -1 );
+ /* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+ /* write image to flash memory */
+ do
+ {
+ g_nmrp_keepalive = 1; /* Foxconn add by Cliff Wang, 03/23/2010 */
+
+ sect_size = flash_get_sector_size(blk_start);
+
+#if defined(DEBUG_FLASH)
+ printf("Image flashing on block: %d\n", blk_start);
+#endif
+
+ // share the blk with psi only when fWholeImage == 0
+ // Foxconn modified by Silver Shih for burn board Id
+ if ((!fWholeImage && blk_start == fInfo.flash_persistent_start_blk) || (fWholeImage == 5))
+ {
+
+#if 0
+ if (size > (sect_size - fInfo.flash_persistent_length))
+ {
+ printf("Image is too big\n");
+ break; // image is too big. Can not overwrite to psi
+ }
+#endif
+
+ if ((pTempBuf = (unsigned char *) KMALLOC(sect_size, sizeof(long))) == NULL)
+ {
+ printf("Failed to allocate memory with size: %d\n", sect_size);
+ break;
+ }
+ flash_read_buf((unsigned short)blk_start, 0, pTempBuf, sect_size);
+ memcpy(pTempBuf, string, size);
+ flash_sector_erase_int(blk_start); // erase blk before flash
+
+
+ if (flash_write_buf(blk_start, 0, pTempBuf, sect_size) == sect_size)
+ size = 0; // break out and say all is ok
+ break;
+ }
+
+ flash_sector_erase_int(blk_start); // erase blk before flash
+
+ if (sect_size > size)
+ {
+ if (size & 1)
+ size++;
+ sect_size = size;
+ }
+ if (flash_write_buf(blk_start, 0, string, sect_size) != sect_size) {
+ if( flash_get_flash_type() != FLASH_IFC_NAND )
+ break;
+ blk_start++;
+ }
+ else {
+ printf(".");
+ blk_start++;
+ string += sect_size;
+ size -= sect_size;
+
+ /* Foxconn added start by jenny @NMRP */
+ if(nmrp_server_detected==1) // in NMRP mode
+ {
+ if(blk_start - savedBlkStart == 30)
+ {
+ savedBlkStart = blk_start;
+ printf("\n");
+ NMRPKeepAlive();
+ }
+ }
+ /* Foxconn added end by jenny @NMRP */
+ }
+ } while (size > 0);
+ g_nmrp_keepalive = 0; /* Foxconn added by jenny add for timeout */
+
+#if 0 /* Foxconn removed by EricHuang */
+ if (size == 0 && fWholeImage && savedSize > FLASH_LENGTH_BOOT_ROM)
+ {
+ // If flashing a whole image, erase to end of flash.
+ while( blk_start < total_blks )
+ {
+ flash_sector_erase_int(blk_start);
+ printf(".");
+ blk_start++;
+ }
+ }
+#endif
+
+ printf("\n\n");
+
+ if( size == 0 )
+ sts = 0; // ok
+ else
+ sts = blk_start; // failed to flash this sector
+
+ g_nmrp_keepalive = 0; /* Foxconn jenny add for timeout */
+ return sts;
+}
+
+unsigned long kerSysReadFromFlash( void *toaddr, unsigned long fromaddr,
+ unsigned long len )
+{
+ int sect = flash_get_blk((int) fromaddr);
+ unsigned char *start = flash_get_memptr(sect);
+ flash_read_buf( sect, (int) fromaddr - (int) start, toaddr, len );
+
+ return(len);
+}
+
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_uart.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_uart.c
new file mode 100755
index 0000000..3b2ce63
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/dev_bcm63xx_uart.c
@@ -0,0 +1,211 @@
+#include "cfe.h"
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+
+#include "sbmips.h"
+#include "bsp_config.h"
+
+#include "bcm_hwdefs.h"
+#include "bcm_map.h"
+
+static void bcm63xx_uart_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+static int bcm63xx_uart_open(cfe_devctx_t *ctx);
+static int bcm63xx_uart_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int bcm63xx_uart_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int bcm63xx_uart_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int bcm63xx_uart_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int bcm63xx_uart_close(cfe_devctx_t *ctx);
+
+const static cfe_devdisp_t bcm63xx_uart_dispatch = {
+ bcm63xx_uart_open,
+ bcm63xx_uart_read,
+ bcm63xx_uart_inpstat,
+ bcm63xx_uart_write,
+ bcm63xx_uart_ioctl,
+ bcm63xx_uart_close,
+ NULL,
+ NULL
+};
+
+
+const cfe_driver_t bcm63xx_uart = {
+ "BCM63xx DUART",
+ "uart",
+ CFE_DEV_SERIAL,
+ &bcm63xx_uart_dispatch,
+ bcm63xx_uart_probe
+};
+
+
+typedef struct bcm63xx_uart_s {
+ int baudrate;
+} bcm63xx_uart_t;
+
+
+static void bcm63xx_set_baudrate( bcm63xx_uart_t * softc )
+{
+ uint32_t baudwd;
+
+ baudwd = (FPERIPH / softc->baudrate) / 16;
+ if( baudwd & 0x1 ) {
+ baudwd = baudwd / 2;
+ } else {
+ baudwd = baudwd / 2 - 1;
+ }
+ UART->baudword = baudwd;
+}
+
+
+static void bcm63xx_uart_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ bcm63xx_uart_t * softc;
+ char descr[80];
+
+ /* enable the transmitter interrupt? */
+
+ /*
+ * probe_a is the DUART base address.
+ * probe_b is the channel-number-within-duart (0 or 1)
+ * probe_ptr is unused.
+ */
+ softc = (bcm63xx_uart_t *) KMALLOC(sizeof(bcm63xx_uart_t),0);
+ if (softc) {
+ xsprintf( descr, "%s channel %d", drv->drv_description, probe_b );
+ cfe_attach( drv, softc, NULL, descr );
+ }
+}
+
+static int bcm63xx_uart_open(cfe_devctx_t *ctx)
+{
+ bcm63xx_uart_t * softc = ctx->dev_softc;
+
+ /* Enable the UART clock */
+ softc->baudrate = CFG_SERIAL_BAUD_RATE;
+ bcm63xx_set_baudrate( softc );
+
+ UART->control = BRGEN | TXEN | RXEN;
+ UART->config = BITS8SYM | ONESTOP;
+ UART->fifoctl = RSTTXFIFOS | RSTRXFIFOS;
+ UART->intMask = 0;
+
+ return 0;
+}
+
+
+static int bcm63xx_uart_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ unsigned char * bptr;
+ int blen;
+ uint32_t status;
+ char inval;
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+
+ while (blen > 0) {
+ status = UART->intStatus;
+ if(status & (RXOVFERR | RXPARERR | RXFRAMERR | RXBRK)) {
+ /* RX over flow */
+ if(status & RXOVFERR) {
+ /* reset RX FIFO to clr interrupt */
+ UART->fifoctl |= RSTRXFIFOS;
+ }
+
+ /* other errors just read the bad character to clear the bit */
+ inval = UART->Data;
+ }
+ else if(status & RXFIFONE) {
+ *bptr++ = UART->Data;
+ blen--;
+ }
+ else
+ break;
+ }
+
+ buffer->buf_retlen = buffer->buf_length - blen;
+ return 0;
+}
+
+
+static int bcm63xx_uart_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
+{
+ inpstat->inp_status = UART->intStatus & RXFIFONE;
+ return 0;
+}
+
+
+static int bcm63xx_uart_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ unsigned char * bptr;
+ int blen;
+ uint32_t status;
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+
+ status = 0;
+ while( (blen > 0) && !status ) {
+ /* Wait for the buffer to empty before we write the next character */
+ /* FIXME - The serial port should be able to accept more than one */
+ /* character at a time. Why doesn't it work though? */
+ do {
+ status = UART->intStatus & TXFIFOEMT;
+ } while( !status );
+ UART->Data = *bptr;
+ bptr++;
+ blen--;
+
+ status = UART->intStatus & (TXOVFERR|TXUNDERR);
+ }
+
+ if( status ) {
+ /* Reset TX FIFO */
+ UART->fifoctl |= RSTTXFIFOS;
+ blen++;
+ }
+
+ buffer->buf_retlen = buffer->buf_length - blen;
+ return 0;
+}
+
+
+static int bcm63xx_uart_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ bcm63xx_uart_t * softc = ctx->dev_softc;
+ unsigned int * info = (unsigned int *) buffer->buf_ptr;
+
+ switch ((int)buffer->buf_ioctlcmd) {
+ case IOCTL_SERIAL_GETSPEED:
+ *info = softc->baudrate;
+ break;
+ case IOCTL_SERIAL_SETSPEED:
+ softc->baudrate = *info;
+ bcm63xx_set_baudrate( softc );
+ break;
+ case IOCTL_SERIAL_GETFLOW:
+ *info = SERIAL_FLOW_NONE;
+ break;
+ case IOCTL_SERIAL_SETFLOW:
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int bcm63xx_uart_close(cfe_devctx_t *ctx)
+{
+ /* Turn off the UART clock. */
+ return 0;
+}
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/html/ul.html b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/html/ul.html
new file mode 100755
index 0000000..a663a35
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/html/ul.html
@@ -0,0 +1,48 @@
+<html>
+ <head>
+ <meta HTTP-EQUIV='Pragma' CONTENT='no-cache'>
+ <script language="javascript">
+<!-- hide
+
+var progress = 0;
+
+function isInProgress() {
+ if ( progress == 0 ) {
+ progress = 1;
+ return true;
+ }
+ alert('Upload software is in progress. Please wait for a minute.');
+ return false;
+}
+
+// done hiding -->
+</script>
+ </head>
+ <body>
+ <blockquote>
+ <form method='post' ENCTYPE='multipart/form-data' action='upload.cgi' onSubmit='return isInProgress();'>
+ <b>Update Software</b><br>
+ <br>
+ <b>Step 1:</b> Obtain an updated software image file from your ISP.<br>
+ <br>
+ <b>Step 2:</b> Enter the path to the image file location in the box below or
+ click the &quot;Browse&quot; button to locate the image file.<br>
+ <br>
+ <b>Step 3:</b> Click the "Update Software" button once to upload the new image
+ file.<br>
+ <br>
+ NOTE: The update process takes about 2 minutes to complete, and your DSL Router
+ will reboot.<br>
+ <br>
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>Software File Name:&nbsp;
+ </td>
+ <td><input type='file' name='filename' size='15'></td>
+ </tr>
+ </table>
+ <p align="center"><input type='submit' value='Update Software'></p>
+ </form>
+ </blockquote>
+ </body>
+</html>
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/html/ulinfo.html b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/html/ulinfo.html
new file mode 100755
index 0000000..1edb2ae
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/html/ulinfo.html
@@ -0,0 +1,60 @@
+<html>
+ <head>
+ <meta HTTP-EQUIV='Pragma' CONTENT='no-cache'>
+ <script language="javascript">
+<!-- hide
+var msg = new Array();
+msg[0] = 'New software is being programmed to the flash memory. The DSL Router will reboot upon completion. This process will take about 2 minutes.';
+msg[1] = 'Image uploading failed. The system is out of memory. The DSL Router is rebooting.';
+msg[2] = 'Image uploading failed. No image file was selected.';
+msg[3] = 'Image uploading failed. The selected file contains an illegal image.';
+msg[4] = 'Image uploading failed. The selected file contains an illegal image.';
+msg[5] = 'Image uploading failed. The selected file contains an illegal image.';
+msg[6] = ' ';
+msg[7] = 'Image uploading failed. The selected file contains an illegal image.';
+
+var idxStr = '<%%>';
+
+function getMsgIndex() {
+ var idxNum = parseInt(idxStr);
+ if ( isNaN(idxNum) || idxNum < 0 || idxNum > 7 )
+ idxNum = 7;
+
+ return idxNum;
+}
+
+function reboot() {
+ var loc = 'upload.html';
+
+ var code = 'location.assign("' + loc + '")';
+ eval(code);
+}
+
+function frmLoad() {
+ setTimeout('reboot()', 40000);
+}
+
+function btnBack() {
+ var code = 'location.assign("' + 'upload.html' + '")';
+ eval(code);
+}
+
+// done hiding -->
+</script>
+ </head>
+ <body onLoad='frmLoad()'>
+ <blockquote> <b>DSL Router Software Upgrade</b><br>
+ <br>
+ <script language="javascript">
+<!-- hide
+document.write(msg[getMsgIndex()]);
+// done hiding -->
+</script>
+ <br>
+ <br>
+ <center>
+ <input type='button' onClick='btnBack()' value='Back'>
+ </center>
+ </blockquote>
+ </body>
+</html>
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/ram_cfe.mk b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/ram_cfe.mk
new file mode 100755
index 0000000..a540170
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/ram_cfe.mk
@@ -0,0 +1,378 @@
+
+#
+# CFE's version number
+#
+
+include ${TOP}/main/cfe_version.mk
+
+#
+# Default values for certain parameters
+#
+
+CFG_MLONG64 ?= 0
+CFG_LITTLE ?= 0
+CFG_RELOC ?= 0
+CFG_UNCACHED ?= 0
+CFG_NEWRELOC ?= 0
+CFG_BOOTRAM ?= 0
+CFG_VGACONSOLE ?= 0
+CFG_PCI ?= 1
+CFG_LDT_REV_017 ?= 0
+CFG_ZLIB ?= 0
+CFG_BIENDIAN ?= 0
+CFG_DOWNLOAD ?= 0
+CFG_RAMAPP ?= 0
+CFG_USB ?= 0
+
+#
+# Paths to other parts of the firmware. Everything's relative to ${TOP}
+# so that you can actually do a build anywhere you want.
+#
+
+ARCH_TOP = ${TOP}/arch/${ARCH}
+ARCH_SRC = ${ARCH_TOP}/common/src
+ARCH_INC = ${ARCH_TOP}/common/include
+CPU_SRC = ${ARCH_TOP}/cpu/${CPU}/src
+CPU_INC = ${ARCH_TOP}/cpu/${CPU}/include
+
+#
+# It's actually optional to have a 'board'
+# directory. If you don't specify BOARD,
+# don't include the files.
+#
+
+ifneq ("$(strip ${BOARD})","")
+BOARD_SRC = ${ARCH_TOP}/board/${BOARD}/src
+BOARD_INC = ${ARCH_TOP}/board/${BOARD}/include
+endif
+
+#
+# Preprocessor defines for CFE's version number
+#
+
+VDEF = -DCFE_VER_MAJ=${CFE_VER_MAJ} -DCFE_VER_MIN=${CFE_VER_MIN} -DCFE_VER_ECO=${CFE_VER_ECO}
+
+#
+# Construct the list of paths that will eventually become the include
+# paths and VPATH
+#
+
+SRCDIRS = ${ARCH_SRC} ${CPU_SRC} ${LZMZ_SRC} ${BOARD_SRC} ${TOP}/main ${TOP}/vendor ${TOP}/include ${TOP}/net ${TOP}/dev ${TOP}/pci ${TOP}/ui ${TOP}/lib ${TOP}/common ${TOP}/verif ${TOP}/lzma
+
+CFE_INC = ${TOP}/include ${TOP}/pci ${TOP}/net
+
+ifeq ($(strip ${CFG_VGACONSOLE}),1)
+SRCDIRS += ${TOP}/x86emu ${TOP}/pccons
+CFE_INC += ${TOP}/x86emu ${TOP}/pccons
+endif
+
+ifeq ($(strip ${CFG_VAPI}),1)
+SRCDIRS += ${TOP}/verif
+CFE_INC += ${TOP}/verif
+endif
+
+ifeq ($(strip ${CFG_ZLIB}),1)
+SRCDIRS += ${TOP}/zlib
+CFE_INC += ${TOP}/zlib
+endif
+
+
+INCDIRS = $(patsubst %,-I%,$(subst :, ,$(ARCH_INC) $(CPU_INC) $(BOARD_INC) $(CFE_INC)))
+
+VPATH = $(SRCDIRS)
+
+#
+# Bi-endian support: If we're building the little-endian
+# version, use a different linker script so we can locate the
+# ROM at a higher address. You'd think we could do this with
+# normal linker command line switches, but there appears to be no
+# command-line way to override the 'AT' qualifier in the linker script.
+#
+
+CFG_TEXTAT1MB=0
+ifeq ($(strip ${CFG_BIENDIAN}),1)
+ ifeq ($(strip ${CFG_LITTLE}),1)
+ CFG_TEXTAT1MB=1
+ endif
+endif
+
+
+#
+# Configure tools and basic tools flags. This include sets up
+# macros for calling the C compiler, basic flags,
+# and linker scripts.
+#
+
+include ${ARCH_SRC}/tools.mk
+
+#
+# Add some common flags that are used on any architecture.
+#
+
+CFLAGS += -I. $(INCDIRS)
+CFLAGS += -D_CFE_ ${VDEF} -DCFG_BOARDNAME=\"${CFG_BOARDNAME}\" -DCONFIG_MIPS_BRCM
+
+#
+# Add flash driver support.
+#
+# INC_xxx_FLASH_DRIVER is exported from rom_cfe.mk
+
+CFLAGS += -DINC_CFI_FLASH_DRIVER=$(INC_CFI_FLASH_DRIVER)
+CFLAGS += -DINC_SPI_FLASH_DRIVER=$(INC_SPI_FLASH_DRIVER)
+CFLAGS += -DINC_NAND_FLASH_DRIVER=$(INC_NAND_FLASH_DRIVER)
+CFLAGS += -DINC_SPI_PROG_NAND=$(INC_SPI_PROG_NAND)
+
+#
+# Set CFG_TCP=0 to not include the TCP protocol.
+#
+
+CFG_TCP=1
+ifeq ($(strip ${CFG_TCP}),1)
+CFLAGS += -DCFG_TCP
+endif
+
+#
+# Set CFG_WEB_SERVER=0 to not include the web server.
+#
+
+CFG_WEB_SERVER=1
+CFLAGS += -DCFG_WEB_SERVER=${CFG_WEB_SERVER}
+
+#
+# Gross - allow more options to be supplied from command line
+#
+
+ifdef CFG_OPTIONS
+OPTFLAGS = $(patsubst %,-D%,$(subst :, ,$(CFG_OPTIONS)))
+CFLAGS += ${OPTFLAGS}
+endif
+
+
+#
+# IKOS Build
+#
+
+ifeq ($(strip $(BRCM_IKOS)),y)
+CFLAGS += -DCONFIG_BRCM_IKOS
+endif
+
+#
+# This is the makefile's main target. Note that we actually
+# do most of the work in 'ALL' not 'all', since we include
+# other makefiles after this point.
+#
+
+all : build_date.c ALL
+
+#
+# Macros that expand to the list of arch-independent files
+#
+
+LZMAOBJS = LzmaDecode.o dcapi.o
+DEVOBJS =
+## dev_newflash.o dev_null.o dev_promice.o dev_ide_common.o dev_ns16550.o dev_ds17887clock.o dev_flash.o
+LIBOBJS = lib_malloc.o lib_printf.o lib_queue.o lib_string.o lib_string2.o \
+ lib_setjmp.o lib_arena.o
+##lib_hssubr.o lib_physio.o lib_misc.o lib_qsort.o
+
+## Foxconn add start by Cliff Wang, 03/23/2010 ##
+#NETOBJS = net_ether.o net_tftp.o net_ip.o net_udp.o net_dns.o net_arp.o \
+ net_api.o net_tcp.o net_tcpbuf.o
+NETOBJS = net_ether.o net_tftp.o net_ip.o net_udp.o net_dns.o net_arp.o \
+ net_api.o net_tcp.o net_tcpbuf.o net_nmrp.o
+## Foxconn add end by Cliff Wang, 03/23/2010
+
+## dev_tcpconsole.o net_dhcp.o net_icmp.o
+CFEOBJS = cfe_attach.o cfe_iocb_dispatch.o cfe_devfuncs.o \
+ cfe_console.o cfe_mem.o cfe_timer.o \
+ cfe_background.o build_date.o \
+ cfe_xreq.o cfe_filesys.o
+## cfe_error.o cfe_rawfs.o cfe_fatfs.o cfe_httpfs.o cfe_ldr_srec.o cfe_autoboot.o cfe_boot.o cfe_ldr_elf.o cfe_ldr_raw.o cfe_loader.o
+## cfe_main.o nvram_subr.o url.o cfe_savedata.o env_subr.o cfe_zlibfs.o
+
+#UIOBJS = ui_command.o ui_cmddisp.o
+# Foxconn add start by Cliff Wang, 03/23/2010
+UIOBJS = ui_command.o ui_cmddisp.o ui_tftpd.o ui_netcmds.o
+
+## ui_pcicmds.o \ui_tcpcmds.o ui_memcmds.o ui_loadcmds.o ui_flash.o ui_envcmds.o ui_devcmds.o ui_netcmds.o
+## ui_examcmds.o ui_misccmds.o \
+## ui_test_disk.o ui_test_ether.o ui_test_flash.o ui_test_uart.o
+
+#
+# Add more object files if we're supporting PCI
+#
+
+ifeq ($(strip ${CFG_PCI}),1)
+PCIOBJS = pciconf.o ldtinit.o pci_subr.o
+PCIOBJS += pci_devs.o
+DEVOBJS += dev_sp1011.o dev_ht7520.o
+DEVOBJS += dev_ide_pci.o dev_ns16550_pci.o
+DEVOBJS += dev_tulip.o dev_dp83815.o
+CFLAGS += -DCFG_PCI=1
+ifeq ($(strip ${CFG_LDT_REV_017}),1)
+CFLAGS += -DCFG_LDT_REV_017=1
+endif
+ifeq ($(strip ${CFG_DOWNLOAD}),1)
+DEVOBJS += dev_bcm1250.o download.data
+CFLAGS += -DCFG_DOWNLOAD=1
+endif
+endif
+
+#
+# If doing bi-endian, add the compiler switch to change
+# the way the vectors are generated. These switches are
+# only added to the big-endian portion of the ROM,
+# which is located at the real boot vector.
+#
+
+ifeq ($(strip ${CFG_BIENDIAN}),1)
+ ifeq ($(strip ${CFG_LITTLE}),0)
+ CFLAGS += -DCFG_BIENDIAN=1
+ endif
+endif
+
+#
+# Include the makefiles for the architecture-common, cpu-specific,
+# and board-specific directories. Each of these will supply
+# some files to "ALLOBJS". The BOARD directory is optional
+# as some ports are so simple they don't need boad-specific stuff.
+#
+
+include ${ARCH_SRC}/Makefile
+include ${CPU_SRC}/Makefile
+
+ifneq ("$(strip ${BOARD})","")
+include ${BOARD_SRC}/Makefile
+endif
+
+#
+# Add the common object files here.
+#
+
+ALLOBJS += $(LIBOBJS) $(DEVOBJS) $(CFEOBJS) $(VENOBJS) $(UIOBJS) $(NETOBJS) $(LZMAOBJS)
+#$(PCIOBJS)
+
+#
+# VAPI continues to be a special case.
+#
+
+ifeq ($(strip ${CFG_VAPI}),1)
+include ${TOP}/verif/Makefile
+endif
+
+#
+# USB support
+#
+
+ifeq ($(strip ${CFG_USB}),1)
+SRCDIRS += ${TOP}/usb
+CFE_INC += ${TOP}/usb
+include ${TOP}/usb/Makefile
+endif
+
+#
+# If we're doing the VGA console thing, pull in the x86 emulator
+# and the pcconsole subsystem
+#
+
+ifeq ($(strip ${CFG_VGACONSOLE}),1)
+include ${TOP}/x86emu/Makefile
+include ${TOP}/pccons/Makefile
+endif
+
+#
+# If we're including ZLIB, then add its makefile.
+#
+
+ifeq ($(strip ${CFG_ZLIB}),1)
+include ${TOP}/zlib/Makefile
+CFLAGS += -DCFG_ZLIB=1 -DMY_ZCALLOC -DNO_MEMCPY
+endif
+
+#
+# Vendor extensions come next - they live in their own directory.
+#
+
+include ${TOP}/vendor/Makefile
+
+.PHONY : all
+.PHONY : ALL
+.PHONY : build_date.c
+
+#
+# Build the local tools that we use to construct other source files
+#
+
+mkpcidb : ${TOP}/hosttools/mkpcidb.c
+ gcc -o mkpcidb ${TOP}/hosttools/mkpcidb.c
+
+memconfig : ${TOP}/hosttools/memconfig.c
+ gcc -o memconfig -D_MCSTANDALONE_ -D_MCSTANDALONE_NOISY_ -I${TOP}/arch/mips/cpu/sb1250/include ${TOP}/hosttools/memconfig.c ${TOP}/arch/${ARCH}/cpu/${CPU}/src/sb1250_draminit.c
+
+pcidevs_data2.h : mkpcidb ${TOP}/pci/pcidevs_data.h
+ ./mkpcidb > pcidevs_data2.h
+
+mkflashimage : ${TOP}/hosttools/mkflashimage.c
+ gcc -o mkflashimage -I${TOP}/include ${TOP}/hosttools/mkflashimage.c
+
+pci_subr.o : ${TOP}/pci/pci_subr.c pcidevs_data2.h
+
+build_date.c :
+ echo "const char *builddate = \"`date`\";" > build_date.c
+ echo "const char *builduser = \"`whoami`@`hostname`\";" >> build_date.c
+
+#
+# Make a define for the board name
+#
+
+CFLAGS += -D_$(patsubst "%",%,${CFG_BOARDNAME})_
+
+LIBCFE = libcfe.a
+
+%.o : %.c
+ $(GCC) $(CFLAGS) -o $@ $<
+
+%.o : %.S
+ $(GCC) $(CFLAGS) -o $@ $<
+
+%.o : %.html
+ echo unsigned char $*_html[] = { > $*.c
+ hexdump -v -e '" " 12/1 "0x%2.2x, " "\n"' $< | sed -e "s/ 0x .*$\//" -e "\$$s/, *$$//" >> $*.c
+ echo ' };' >> $*.c
+ echo 'int $*_html_size = sizeof($*_html);' >> $*.c
+ echo >> $*.c
+ $(GCC) $(CFLAGS) -o $@ $*.c
+ rm -f $*.c
+
+%.o : %.css
+ echo unsigned char $*_css[] = { > $*.c
+ hexdump -v -e '" " 12/1 "0x%2.2x, " "\n"' $< | sed -e "s/ 0x .*$\//" -e "\$$s/, *$$//" >> $*.c
+ echo ' };' >> $*.c
+ echo 'int $*_css_size = sizeof($*_css);' >> $*.c
+ echo >> $*.c
+ $(GCC) $(CFLAGS) -o $@ $*.c
+ rm -f $*.c
+
+%.o : %.gif
+ echo unsigned char $*_gif[] = { > $*.c
+ hexdump -v -e '" " 12/1 "0x%2.2x, " "\n"' $< | sed -e "s/ 0x .*$\//" -e "\$$s/, *$$//" >> $*.c
+ echo ' };' >> $*.c
+ echo 'int $*_gif_size = sizeof($*_gif);' >> $*.c
+ echo >> $*.c
+ $(GCC) $(CFLAGS) -o $@ $*.c
+ rm -f $*.c
+
+#
+# This rule constructs "libcfe.a" which contains most of the object
+# files.
+#
+
+$(LIBCFE) : $(ALLOBJS)
+ rm -f $(LIBCFE)
+ $(AR) cr $(LIBCFE) $(ALLOBJS)
+ $(RANLIB) $(LIBCFE)
+
+
+
+
+
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/robosw_reg.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/robosw_reg.c
new file mode 100755
index 0000000..15dad53
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/robosw_reg.c
@@ -0,0 +1,615 @@
+/*
+<:copyright-broadcom
+
+ Copyright (c) 2007 Broadcom Corporation
+ All Rights Reserved
+ No portions of this material may be reproduced in any form without the
+ written permission of:
+ Broadcom Corporation
+ 16215 Alton Parkway
+ Irvine, California 92619
+ All information contained in this document is Broadcom Corporation
+ company private, proprietary, and trade secret.
+
+:>
+*/
+
+#include "bcm_map.h"
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+#include "mii.h"
+#include "bcmmii.h"
+#include "sbmips.h"
+#include "cfe_iocb.h"
+#include "cfe_timer.h"
+#include "robosw_reg.h"
+#include "dev_bcm63xx_eth.h"
+#include "bcmSpiRes.h"
+
+static uint32 mii_read(uint32 uPhyAddr, uint32 uRegAddr);
+static void mii_write(uint32 uPhyAddr, uint32 uRegAddr, uint32 data);
+
+static int ext_switch_init(void);
+static int ethsw_spi_ss_id(void);
+static void ethsw_spi_select(int page);
+static void ethsw_spi_rreg(int page, int reg, uint8 *data, int len);
+static void ethsw_spi_wreg(int page, int reg, uint8 *data, int len);
+
+void ethsw_rreg_ext(int access_type, int page, int reg, uint8 *data, int len);
+void ethsw_wreg_ext(int access_type, int page, int reg, uint8 *data, int len);
+
+
+static ETHERNET_MAC_INFO EnetInfo[BP_MAX_ENET_MACS];
+static uint16 PortLinkState[BP_MAX_SWITCH_PORTS];
+
+#define MDIO_BUS 0
+#define SPI_BUS 1
+#define TX_BDS 3
+#define RX_BDS 16
+#define CACHE_ALIGN 16
+#define BUF_LENGTH 160
+extern void _cfe_flushcache(int, uint8_t *, uint8_t *);
+#define INVAL_RANGE(s,l) _cfe_flushcache(CFE_CACHE_INVAL_RANGE,((uint8_t *) (s)),((uint8_t *) (s))+(l))
+
+/* read a value from the MII */
+static uint32 mii_read(uint32 uPhyAddr, uint32 uRegAddr)
+{
+ SWITCH->MdioCtrl = 0x0;
+ SWITCH->MdioCtrl = MdioCtrl_Read | (IsExtPhyId(uPhyAddr) ? MdioCtrl_Ext : 0) |
+ ((uPhyAddr << MdioCtrl_ID_Shift) & MdioCtrl_ID_Mask) |
+ (uRegAddr << MdioCtrl_Addr_Shift);
+ cfe_usleep(100);
+ return SWITCH->MdioData;
+}
+
+/* write a value to the MII */
+static void mii_write(uint32 uPhyAddr, uint32 uRegAddr, uint32 data)
+{
+ SWITCH->MdioCtrl = 0x0;
+ SWITCH->MdioCtrl = MdioCtrl_Write | (IsExtPhyId(uPhyAddr) ? MdioCtrl_Ext : 0) |
+ ((uPhyAddr << MdioCtrl_ID_Shift) & MdioCtrl_ID_Mask) |
+ (uRegAddr << MdioCtrl_Addr_Shift) | data;
+ cfe_usleep(100);
+}
+
+static int clkHz = 781000;
+#if !defined(_BCM96328_)
+static int clk781k = 2;
+#endif
+static int ethsw_spi_ss_id()
+{
+ int slave_select;
+
+ switch(EnetInfo[1].usConfigType) {
+ case BP_ENET_CONFIG_SPI_SSB_0:
+ slave_select = 0;
+ break;
+ case BP_ENET_CONFIG_SPI_SSB_1:
+ slave_select = 1;
+ break;
+ case BP_ENET_CONFIG_SPI_SSB_2:
+ slave_select = 2;
+ break;
+ case BP_ENET_CONFIG_SPI_SSB_3:
+ slave_select = 3;
+ break;
+ default:
+ slave_select = 1;
+ xprintf("Invalid SPI_SS in usConfigType, Assuming 1\n");
+ break;
+ }
+ return slave_select;
+}
+
+static void ethsw_spi_select(int page)
+{
+ unsigned char buf[3];
+ int spi_ss, cid = 0;
+
+ spi_ss = ethsw_spi_ss_id();
+ /* Select new chip */
+ buf[0] = BCM5325_SPI_CMD_NORMAL | BCM5325_SPI_CMD_WRITE |
+ ((cid & BCM5325_SPI_CHIPID_MASK) << BCM5325_SPI_CHIPID_SHIFT);
+
+ /* Select new page */
+ buf[1] = PAGE_SELECT;
+ buf[2] = (char)page;
+#if defined(_BCM96328_)
+ BcmSpi_Write(buf, sizeof(buf), HS_SPI_BUS_NUM, spi_ss, clkHz);
+#else
+ BcmSpi_Write(buf, sizeof(buf), LEG_SPI_BUS_NUM, spi_ss, clkHz);
+#endif
+
+}
+
+static void ethsw_spi_rreg(int page, int reg, uint8 *data, int len)
+{
+ unsigned char buf[64];
+ int rc;
+ int i;
+ int max_check_spi_sts;
+ int prependCnt = BCM5325_SPI_PREPENDCNT, spi_ss, cid = 0;
+
+ spi_ss = ethsw_spi_ss_id();
+
+ ethsw_spi_select(page);
+
+ /* write command byte and register address */
+ buf[0] = BCM5325_SPI_CMD_NORMAL | BCM5325_SPI_CMD_READ |
+ ((cid & BCM5325_SPI_CHIPID_MASK) << BCM5325_SPI_CHIPID_SHIFT);
+ buf[1] = (unsigned char)reg;
+#if defined(_BCM96328_)
+ rc = BcmSpi_Read(buf, prependCnt, 1, HS_SPI_BUS_NUM, spi_ss, clkHz);
+#else
+ rc = BcmSpi_Read(buf, prependCnt, 1, LEG_SPI_BUS_NUM, spi_ss, clkHz);
+#endif
+
+ if (rc == SPI_STATUS_OK) {
+ max_check_spi_sts = 0;
+ do {
+ /* write command byte and read spi_sts address */
+ buf[0] = BCM5325_SPI_CMD_NORMAL | BCM5325_SPI_CMD_READ |
+ ((cid & BCM5325_SPI_CHIPID_MASK) << BCM5325_SPI_CHIPID_SHIFT);
+ buf[1] = (unsigned char)BCM5325_SPI_STS;
+#if defined(_BCM96328_)
+ rc = BcmSpi_Read(buf, prependCnt, 1, HS_SPI_BUS_NUM, spi_ss, clkHz);
+#else
+ rc = BcmSpi_Read(buf, prependCnt, 1, LEG_SPI_BUS_NUM, spi_ss, clkHz);
+#endif
+ if (rc == SPI_STATUS_OK) {
+ /* check the bit 0 RACK bit is set */
+ if (buf[0] & BCM5325_SPI_CMD_RACK) {
+ break;
+ }
+ cfe_usleep(10000);
+ } else {
+ break;
+ }
+ } while (max_check_spi_sts++ < 10);
+
+ if (rc == SPI_STATUS_OK) {
+ for (i = 0; i < len; i++) {
+ buf[0] = BCM5325_SPI_CMD_NORMAL | BCM5325_SPI_CMD_READ |
+ ((cid & BCM5325_SPI_CHIPID_MASK) << BCM5325_SPI_CHIPID_SHIFT);
+ buf[1] = (unsigned char)0xf0;
+#if defined(_BCM96328_)
+ rc = BcmSpi_Read(buf, prependCnt, 1, HS_SPI_BUS_NUM, spi_ss, clkHz);
+#else
+ rc = BcmSpi_Read(buf, prependCnt, 1, LEG_SPI_BUS_NUM, spi_ss, clkHz);
+#endif
+ if (rc == SPI_STATUS_OK) {
+ *(data + (len - i - 1)) = buf[0];
+ }
+ }
+ }
+ }
+}
+
+static void ethsw_spi_wreg(int page, int reg, uint8 *data, int len)
+{
+ unsigned char buf[64];
+ int i;
+ int spi_ss, cid = 0;
+
+ ethsw_spi_select(page);
+
+ spi_ss = ethsw_spi_ss_id();
+ buf[0] = BCM5325_SPI_CMD_NORMAL | BCM5325_SPI_CMD_WRITE |
+ ((cid & BCM5325_SPI_CHIPID_MASK) << BCM5325_SPI_CHIPID_SHIFT);
+
+ buf[1] = (char)reg;
+ for (i = 0; i < len; i++) {
+ /* Write the data out in LE format to the switch */
+ buf[BCM5325_SPI_PREPENDCNT+i] = *(data + (len - i - 1));
+ }
+ BcmSpi_Write(buf, len+BCM5325_SPI_PREPENDCNT, LEG_SPI_BUS_NUM, spi_ss, clkHz);
+}
+
+/* External switch register access through MDC/MDIO */
+static void ethsw_mdio_rreg(int page, int reg, uint8 *data, int len)
+{
+ uint32 cmd, res, ret;
+ int max_retry = 0;
+
+ cmd = (page << REG_PPM_REG16_SWITCH_PAGE_NUMBER_SHIFT) | REG_PPM_REG16_MDIO_ENABLE;
+ mii_write(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG16, cmd);
+
+ cmd = (reg << REG_PPM_REG17_REG_NUMBER_SHIFT) | REG_PPM_REG17_OP_READ;
+ mii_write(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG17, cmd);
+
+ do {
+ res = mii_read(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG17);
+ cfe_usleep(10);
+ } while (((res & (REG_PPM_REG17_OP_WRITE|REG_PPM_REG17_OP_READ)) != REG_PPM_REG17_OP_DONE) &&
+ (max_retry++ < 5));
+
+ ret = 0;
+ ret |= mii_read(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG24) << 0;
+ ret |= mii_read(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG25) << 16;
+ switch (len) {
+ case 1:
+ *data = (uint8)ret;
+ break;
+ case 2:
+ *(uint16 *)data = (uint16)ret;
+ break;
+ case 4:
+ *(uint32 *)data = ret;
+ break;
+ }
+}
+
+static void ethsw_mdio_wreg(int page, int reg, uint8 *data, int len)
+{
+ uint32 cmd, res;
+ uint32 val = 0;
+ int max_retry = 0;
+
+ switch (len) {
+ case 1:
+ val = *data;
+ break;
+ case 2:
+ val = *(uint16 *)data;
+ break;
+ case 4:
+ val = *(uint32 *)data;
+ break;
+ }
+ cmd = (page << REG_PPM_REG16_SWITCH_PAGE_NUMBER_SHIFT) | REG_PPM_REG16_MDIO_ENABLE;
+ mii_write(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG16, cmd);
+
+ cmd = val>>0 & 0xffff;
+ mii_write(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG24, cmd);
+ cmd = val>>16 & 0xffff;
+ mii_write(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG25, cmd);
+ cmd = 0;
+ mii_write(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG26, cmd);
+ cmd = 0;
+ mii_write(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG27, cmd);
+
+ cmd = (reg << REG_PPM_REG17_REG_NUMBER_SHIFT) | REG_PPM_REG17_OP_WRITE;
+ mii_write(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG17, cmd);
+
+ do {
+ res = mii_read(PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG17);
+ cfe_usleep(10);
+ } while (((res & (REG_PPM_REG17_OP_WRITE|REG_PPM_REG17_OP_READ)) != REG_PPM_REG17_OP_DONE) &&
+ (max_retry++ < 5));
+}
+
+void ethsw_rreg_ext(int access_type, int page, int reg, uint8 *data, int len)
+{
+ if (access_type == MDIO_BUS) {
+ ethsw_mdio_rreg(page, reg, data, len);
+
+ } else {
+ ethsw_spi_rreg(page, reg, data, len);
+ }
+}
+
+void ethsw_wreg_ext(int access_type, int page, int reg, uint8 *data, int len)
+{
+ if (access_type == MDIO_BUS) {
+ ethsw_mdio_wreg(page, reg, data, len);
+ } else {
+ ethsw_spi_wreg(page, reg, data, len);
+ }
+}
+
+int ext_switch_init(void)
+{
+ uint8 data8;
+ uint32 data32, access_type;
+#if !defined(_BCM96328_)
+ uint32 clkSave;
+#endif
+
+ switch (EnetInfo[1].usConfigType) {
+ case BP_ENET_CONFIG_SPI_SSB_0:
+ case BP_ENET_CONFIG_SPI_SSB_1:
+ case BP_ENET_CONFIG_SPI_SSB_2:
+ case BP_ENET_CONFIG_SPI_SSB_3:
+ access_type = SPI_BUS;
+#if !defined(_BCM96328_)
+ clkSave = SPI->spiClkCfg & SPI_CLK_MASK;
+ xprintf("spiClkCfg = %x; clkSave = %d \n", SPI->spiClkCfg, clkSave);
+ SPI->spiClkCfg = (SPI->spiClkCfg & ~SPI_CLK_MASK) | clk781k;
+#endif
+ break;
+
+ case BP_ENET_CONFIG_MDIO_PSEUDO_PHY:
+ access_type = MDIO_BUS;
+ break;
+
+ default:
+ xprintf("Unknown PHY configuration type\n");
+ return -1;
+ }
+
+ ethsw_rreg_ext(access_type, PAGE_MANAGEMENT, REG_DEVICE_ID, (uint8 *)&data32, sizeof(data32));
+ xprintf("External switch id = %x \n", data32);
+
+ if (data32 == 0x53115)
+ {
+ /* setup Switch MII1 port state override */
+ data8 = (REG_CONTROL_MPSO_MII_SW_OVERRIDE |
+ REG_CONTROL_MPSO_SPEED1000 |
+ REG_CONTROL_MPSO_FDX |
+ REG_CONTROL_MPSO_LINKPASS);
+ ethsw_wreg_ext(access_type, PAGE_CONTROL,
+ REG_CONTROL_MII1_PORT_STATE_OVERRIDE, &data8, sizeof(data8));
+ /* management mode, enable forwarding */
+ data8 = REG_SWITCH_MODE_FRAME_MANAGE_MODE | REG_SWITCH_MODE_SW_FWDG_EN;
+ ethsw_wreg_ext(access_type, PAGE_CONTROL,
+ REG_SWITCH_MODE, &data8, sizeof(data8));
+ /* Enable IMP Port */
+ data8 = ENABLE_MII_PORT;
+ ethsw_wreg_ext(access_type, PAGE_MANAGEMENT,
+ REG_GLOBAL_CONFIG, &data8, sizeof(data8));
+ /* Disable BRCM Tag for IMP */
+ data8 = ~REG_BRCM_HDR_ENABLE;
+ ethsw_wreg_ext(access_type, PAGE_MANAGEMENT,
+ REG_BRCM_HDR_CTRL, &data8, sizeof(data8));
+ /* enable rx bcast, ucast and mcast of imp port */
+ data8 = (REG_MII_PORT_CONTROL_RX_UCST_EN |
+ REG_MII_PORT_CONTROL_RX_MCST_EN |
+ REG_MII_PORT_CONTROL_RX_BCST_EN);
+ ethsw_wreg_ext(access_type, PAGE_CONTROL, REG_MII_PORT_CONTROL, &data8, sizeof(data8));
+ }
+
+#if !defined(_BCM96328_)
+ if (access_type == SPI_BUS)
+ SPI->spiClkCfg = (SPI->spiClkCfg & ~SPI_CLK_MASK) | clkSave;
+#endif
+ return 0;
+}
+
+
+void robosw_init(void)
+{
+ int port;
+
+ BpGetEthernetMacInfo(EnetInfo, BP_MAX_ENET_MACS);
+
+ // Power up and reset EPHYs
+ GPIO->RoboswEphyCtrl = 0;
+ cfe_usleep(1000);
+
+ // Take EPHYs out of reset
+ GPIO->RoboswEphyCtrl =
+ EPHY_RST_4 |
+ EPHY_RST_3 |
+ EPHY_RST_2 |
+ EPHY_RST_1;
+ cfe_usleep(1000);
+
+#if defined(_BCM96328_) || defined(_BCM96362_)
+ GPIO->RoboswSwitchCtrl |= (RSW_MII_DUMB_FWDG_EN | RSW_HW_FWDG_EN);
+#endif
+#if defined(_BCM96368_) || defined(_BCM96816_)
+ GPIO->RoboswEphyCtrl |= (RSW_MII_DUMB_FWDG_EN | RSW_HW_FWDG_EN);
+#endif
+
+ // Enable Switch clock
+ PERF->blkEnables |= ROBOSW_CLK_EN;
+#if defined(_BCM96368_)
+ PERF->blkEnables |= SWPKT_SAR_CLK_EN | SWPKT_USB_CLK_EN;
+#endif
+#if defined(_BCM96816_)
+ PERF->blkEnables |= SWPKT_GPON_CLK_EN | SWPKT_USB_CLK_EN;
+#endif
+
+ cfe_usleep(1000);
+
+ PERF->softResetB &= ~SOFT_RST_SWITCH;
+ cfe_usleep(1000);
+ PERF->softResetB |= SOFT_RST_SWITCH;
+ cfe_usleep(1000);
+
+ /* Disable Rx and Tx on all Ethernet Ports */
+ for (port = 0; port < EPHY_PORTS; port++) {
+ SWITCH->PortCtrl[port] = 0x03;
+ }
+
+ if (EnetInfo[1].ucPhyType == BP_ENET_EXTERNAL_SWITCH) {
+ ext_switch_init();
+ }
+
+}
+
+void robosw_configure_ports()
+{
+ uint16 data;
+ int i;
+
+ for (i = 0; i < 6; i++) {
+ if ((EnetInfo[0].sw.port_map & (1 << i)) != 0) {
+ if (EnetInfo[0].sw.phy_id[i] == 0xff) {
+#if defined(_BCM96368_)
+ if (i == 4)
+ GPIO->GPIOBaseMode |= (EN_GMII1);
+ if (i == 5)
+ GPIO->GPIOBaseMode |= (EN_GMII2);
+#endif
+ continue;
+ }
+ if (IsWanPort(EnetInfo[0].sw.phy_id[i])) {
+ *(SWITCH_PBVLAN + i) = PBMAP_MIPS;
+ SWITCH->DisableLearn |= (1 << i);
+ }
+ // Reset
+ mii_write(EnetInfo[0].sw.phy_id[i], MII_BMCR, BMCR_RESET);
+ PortLinkState[i] = 0;
+ if (!IsExtPhyId(EnetInfo[0].sw.phy_id[i])) {
+ // Configure PHY link/act LED
+#if defined(_BCM96368_)
+ // Enable status change notification */
+ mii_write(EnetInfo[0].sw.phy_id[i], MII_INTERRUPT, MII_INTR_ENABLE);
+ // Configure LEDs
+ data = mii_read(EnetInfo[0].sw.phy_id[i], MII_RESERVED_1B);
+ mii_write(EnetInfo[0].sw.phy_id[i], MII_RESERVED_1B, data | MII_RESERVED_1B_ACT_LED);
+#elif defined(_BCM96816_)
+ // Configure LEDs
+ mii_write(EnetInfo[0].sw.phy_id[i], 0x1c, 0xa410);
+#elif defined(_BCM96328_) || defined(_BCM96362_)
+ // Configure LEDs
+ // Enable Shadow register 2
+ data = mii_read(EnetInfo[0].sw.phy_id[i], MII_BRCM_TEST);
+ mii_write(EnetInfo[0].sw.phy_id[i], MII_BRCM_TEST, (data | MII_BRCM_TEST_SHADOW2_ENABLE));
+ // Set LED0 to speed. Set LED1 to blinky link
+ mii_write(EnetInfo[0].sw.phy_id[i], 0x15, 0x71);
+ // Disable Shadow register 2
+ mii_write(EnetInfo[0].sw.phy_id[i], MII_BRCM_TEST, (data & ~MII_BRCM_TEST_SHADOW2_ENABLE));
+#endif
+ } else {
+#if defined(_BCM96368_)
+ if (i == 4)
+ GPIO->GPIOBaseMode |= (EN_GMII1);
+ if (i == 5)
+ GPIO->GPIOBaseMode |= (EN_GMII2);
+#endif
+#if defined(_BCM96816_)
+ if (i == 2)
+ GPIO->GPIOBaseMode |= (EN_GMII1);
+ if (i == 3)
+ GPIO->GPIOBaseMode |= (EN_GMII2);
+#endif
+#if defined(_BCM96362_)
+ if (i == 4)
+ GPIO->RoboswSwitchCtrl |= (RSW_MII_SEL_2P5V << RSW_MII_SEL_SHIFT);
+ if (i == 5)
+ GPIO->RoboswSwitchCtrl |= (RSW_MII_2_IFC_EN | (RSW_MII_SEL_2P5V << RSW_MII_2_SEL_SHIFT));
+#endif
+#if defined(_BCM96328_)
+ if (i == 4)
+ MISC->miscPadCtrlHigh |= (MISC_MII_SEL_2P5V << MISC_MII_SEL_SHIFT);
+#endif
+ // Reset
+ mii_write(EnetInfo[0].sw.phy_id[i], MII_BMCR, BMCR_RESET);
+ // Enable auto-negotiation
+ mii_write(EnetInfo[0].sw.phy_id[i], MII_ANAR, ANAR_TXFD | ANAR_TXHD | ANAR_10FD | ANAR_10HD | PSB_802_3);
+
+ // Configure LED for link/activity
+ data = MII_1C_SHADOW_LED_CONTROL << MII_1C_SHADOW_REG_SEL_S;
+ mii_write(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C, data);
+ data = mii_read(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C);
+ data |= ACT_LINK_LED_ENABLE;
+ data |= MII_1C_WRITE_ENABLE;
+ mii_write(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C, data);
+
+ data = mii_read(EnetInfo[0].sw.phy_id[i], MII_PHYIDR2);
+ if ((data & BCM_PHYID_M) == (BCM54610_PHYID2 & BCM_PHYID_M)) {
+ // Configure RGMII timing for 54610 GPHY
+ data = MII_1C_SHADOW_CLK_ALIGN_CTRL << MII_1C_SHADOW_REG_SEL_S;
+ mii_write(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C, data);
+ data = mii_read(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C);
+ data &= (~GTXCLK_DELAY_BYPASS_DISABLE);
+ data |= MII_1C_WRITE_ENABLE;
+ mii_write(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C, data);
+
+ // Configure LOM LED Mode
+ data = MII_1C_EXTERNAL_CONTROL_1 << MII_1C_SHADOW_REG_SEL_S;
+ mii_write(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C, data);
+ data = mii_read(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C);
+ data |= LOM_LED_MODE;
+ data |= MII_1C_WRITE_ENABLE;
+ mii_write(EnetInfo[0].sw.phy_id[i], MII_REGISTER_1C, data);
+ }
+ }
+ // Restart auto-negotiation
+ data = mii_read(EnetInfo[0].sw.phy_id[i], MII_BMCR);
+ mii_write(EnetInfo[0].sw.phy_id[i], MII_BMCR, data | BMCR_RESTARTAN);
+ }
+ }
+
+#if defined(_BCM96816_)
+ // Disable SERDES, MoCA, USB and GPON port
+ SWITCH->PortOverride[SERDES_PORT_ID] = PortOverride_Enable;
+ SWITCH->PortOverride[MOCA_PORT_ID] = PortOverride_Enable;
+ SWITCH->PortOverride[USB_PORT_ID] = PortOverride_Enable;
+ SWITCH->PortOverride[GPON_PORT_ID] = PortOverride_Enable;
+#endif
+
+#if defined(_BCM96328_) || defined(_BCM96362_)
+ // Ports 6 and 7 are not used on 6328 and 6362
+ SWITCH->PortOverride[PORT_6_PORT_ID] = PortOverride_Enable;
+ SWITCH->PortOverride[PORT_7_PORT_ID] = PortOverride_Enable;
+#endif
+
+#if defined(_BCM96368_)
+ // Disable SAR and USB port
+ SWITCH->PortOverride[USB_PORT_ID] = PortOverride_Enable;
+ SWITCH->PortOverride[SAR_PORT_ID] = PortOverride_Enable;
+#endif
+
+ // Enable the GMII clocks.
+ SWITCH->ImpRgmiiCtrlP4 |= ImpRgmiiCtrl_GMII_En;
+ /* RGMII Delay Programming. Enable ID mode */
+ SWITCH->ImpRgmiiCtrlP4 |= ImpRgmiiCtrl_Timing_Sel;
+
+#if !defined(_BCM96328_)
+ SWITCH->ImpRgmiiCtrlP5 |= ImpRgmiiCtrl_GMII_En;
+ SWITCH->ImpRgmiiCtrlP5 |= ImpRgmiiCtrl_Timing_Sel;
+#endif
+
+ // Reset MIB counters
+ SWITCH->GlbMgmt = GlbMgmt_ResetMib;
+ cfe_usleep(100);
+ SWITCH->GlbMgmt = 0;
+
+ SWITCH->ImpOverride |= ImpOverride_Force | ImpOverride_Linkup;
+
+}
+
+void robosw_check_ports()
+{
+ uint16 data;
+ uint8 PortOverride;
+ int i;
+
+ for (i = 0; i < EPHY_PORTS; i++) {
+ if ((EnetInfo[0].sw.port_map & (1 << i)) != 0) {
+ if (EnetInfo[0].sw.phy_id[i] == 0xff) {
+ PortOverride = PortOverride_Enable | PortOverride_1000Mbs |
+ PortOverride_Fdx | PortOverride_Linkup;
+ if ((SWITCH->PortOverride[i] & PortOverride) != PortOverride) {
+ SWITCH->PortOverride[i] = PortOverride;
+ SWITCH->PortCtrl[i] = 0;
+ PortLinkState[i] = 1;
+ }
+ continue;
+ }
+ PortOverride = PortOverride_Enable;
+ data = mii_read(EnetInfo[0].sw.phy_id[i], MII_ASR);
+ if (PortLinkState[i] != MII_ASR_LINK(data)) {
+
+ if (MII_ASR_LINK(data))
+ PortOverride |= PortOverride_Linkup;
+
+ if (MII_ASR_DONE(data)) {
+ if (MII_ASR_FDX(data))
+ PortOverride |= PortOverride_Fdx;
+ if (MII_ASR_1000(data))
+ PortOverride |= PortOverride_1000Mbs;
+ else if (MII_ASR_100(data))
+ PortOverride |= PortOverride_100Mbs;
+ else
+ PortOverride |= PortOverride_10Mbs;
+ }
+
+ SWITCH->PortOverride[i] = PortOverride;
+
+ if(PortOverride & PortOverride_Linkup) {
+ /* Enable Rx and Tx */
+ SWITCH->PortCtrl[i] = 0;
+ }
+
+ PortLinkState[i] = MII_ASR_LINK(data);
+ }
+ }
+ }
+}
+
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_rom/src/Makefile b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/Makefile
new file mode 100755
index 0000000..808ddc2
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/Makefile
@@ -0,0 +1,23 @@
+ifeq ($(strip ${CFG_BOARDNAME}),"BCM96328")
+BSPOBJS += \
+ bcm63xx_impl1_rom_boot.o
+endif
+ifeq ($(strip ${CFG_BOARDNAME}),"BCM96362")
+BSPOBJS += \
+ bcm63xx_impl1_rom_boot.o
+endif
+ifeq ($(strip ${CFG_BOARDNAME}),"BCM96368")
+BSPOBJS += \
+ bcm6368_rom_boot.o \
+ bcm6368_sdramDqs.o
+endif
+ifeq ($(strip ${CFG_BOARDNAME}),"BCM96816")
+BSPOBJS += \
+ bcm63xx_impl1_rom_boot.o
+endif
+ifeq ($(strip ${INC_NAND_FLASH_DRIVER}),1)
+BSPOBJS += \
+ nandflash.o
+endif
+BSPOBJS += \
+ bcm63xx_main.o
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_rom_boot.S b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_rom_boot.S
new file mode 100755
index 0000000..f1cba19
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_rom_boot.S
@@ -0,0 +1,548 @@
+#include "sbmips.h"
+#include "bsp_config.h"
+
+#include "6368_cpu.h"
+#include "6368_common.h"
+#include "bcm_hwdefs.h"
+#include "boardparms.h"
+#include "mipsmacros.h"
+
+#define SETLEDS1(a,b,c,d) \
+ li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \
+ bal board_setleds
+
+/* *********************************************************************
+ * BOARD_EARLYINIT()
+ *
+ * Initialize board registers. This is the earliest
+ * time the BSP gets control. This routine cannot assume that
+ * memory is operational, and therefore all code in this routine
+ * must run from registers only. The $ra register must not
+ * be modified, as it contains the return address.
+ *
+ * This routine will be called from uncached space, before
+ * the caches are initialized. If you want to make
+ * subroutine calls from here, you must use the CALLKSEG1 macro.
+ *
+ * Among other things, this is where the GPIO registers get
+ * programmed to make on-board LEDs function, or other startup
+ * that has to be done before anything will work.
+ *
+ * Input parameters:
+ * a0 - Flash base address (address of MIPS reset)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(board_earlyinit)
+
+ .set noreorder
+
+ mfc0 t1, C0_BCM_CONFIG, 3
+ li t2, CP0_CMT_TPID
+ and t1, t2
+ bnez t1, 2f # if we are running on thread 1, skip init
+ nop
+
+#if 0
+ /* wait for a while to allow catch by jtag debugger */
+ li t8, -(200000000*3) /* we will count up to 0 to delay a couple of seconds */
+ /* and give the emulator a chance to catch us */
+ mtc0 t8, C0_COUNT
+catchloop:
+ bltz t8, catchloop
+ mfc0 t8, C0_COUNT
+#endif
+
+ /**--------------------------------------------------------------**/
+ /** platform specific code **/
+ /**--------------------------------------------------------------**/
+ /**----- Enable I Cache -----------------------------------------**/
+ mfc0 t1, C0_BCM_CONFIG
+ or t1, (CP0_BCM_CFG_ICSHEN | CP0_BCM_CFG_DCSHEN)
+ mtc0 t1, C0_BCM_CONFIG # Enable I Cache
+
+ // In the begining MIPS core registers are mapped to 0xbfax_xxxx
+ li t1, 0x1FA0000C # Set up CBR to 1FAx_xxxx
+ mtc0 t1, C0_BCM_CONFIG, 6
+
+ li t1, MIPS_BASE_BOOT
+ lw t2, MIPS_LMB_CR(t1)
+ or t2, 0xC0000000 # enable ffxx_xxxx space
+ sw t2, MIPS_LMB_CR(t1)
+ li t2, 0xFFF80001 # SBR FFF8_xxxx and enable
+ sw t2, MIPS_SBR(t1)
+
+ // Now map MIPS core registers to 0xFF4x_xxxx space
+ li t1, 0xFF40000C # CBR FF4x_xxxx (and reserved bits 0xc).
+ mtc0 t1, C0_BCM_CONFIG, 6
+
+ /**----- Initialize EBI -----------------------------------------**/
+ li t1, MPI_BASE
+ li t2, EBI_SIZE_32M
+ or t2, a0
+ sw t2, CS0BASE(t1) # CS[0] Base
+ li t2, THREEWT|EBI_WORD_WIDE|EBI_ENABLE
+ sw t2, CS0CNTL(t1) # CS[0] Control
+
+ /**----- Initialize Serial --------------------------------------**/
+ li t3, ((FPERIPH / 115200) / 16)
+ /*
+ # Baudword = (FPeriph)/Baud/32-1. We have to perform rounding
+ # and subtraction. Above we divided by 16 (instead of 32). If
+ # bit0 is set, we round up. However, we then subtract 1, so final
+ # result should be t3/2. If bit0 is 0, then we truncate and subtract
+ # 1, t3=t3/2-1.
+ */
+ andi t0, t3, 0x1
+ bne t0,zero,1f # do shift only (in delay slot)
+ # and jump to apply
+ srl t3,1 # do divide by 2
+ addiu t3, -1 # subtract 1
+1:
+
+ # t3 contains the UART BAUDWORD
+ li t0, UART_BASE
+ sw t3, UART0BAUD(t0) # Store BaudRate
+ li t1, BITS8SYM|ONESTOP
+ sb t1, UART0CONFIG(t0) # 8 Bits/1 Stop
+ li t1, TXEN|RXEN|BRGEN
+ sb t1, UART0CONTROL(t0) # Enable, No Parity
+ move t1, zero
+ sh t1, UART0INTMASK(t0)
+
+ .set reorder
+2:
+ j ra
+END(board_earlyinit)
+
+/* *********************************************************************
+ * BOARD_DRAMINFO
+ *
+ * Return the address of the DRAM information table
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * v0 - DRAM info table, return 0 to use default table
+ ********************************************************************* */
+LEAF(board_draminfo)
+ j ra
+END(board_draminfo)
+
+/* *********************************************************************
+ * BOARD_DRAMINIT
+ *
+ * This routine should activate memory.
+ *
+ * Input parameters:
+ * None
+ *
+ * Return value:
+ * None
+ *
+ * Registers used:
+ * can use all registers.
+ ********************************************************************* */
+LEAF(board_draminit)
+ .set noreorder
+
+ li t0, MEMC_BASE
+ li t1, DDR_BASE
+
+ li t4, (7 << 28) | (7 << 24) | (1 << 20) | (7 << 16) # UBUS_CNTR_CYCLES = 7, LLMB_CNTR_CYCLES = 7, PH_CNTR_EN = 1, PH_CNTR_CYCLES = 7
+ sw t4, DDR_MIPS_PHASE_CNTL(t1)
+
+ # Calculate a value for a 90 degree phase shift.
+
+ lw t2, DDR_MIPSDDR_PLL_MDIV(t1)
+ srl t2, 8 # Shift and mask off DDR_MDIV
+ and t2, 0xff
+ sll t2, 2 # PI_steps = (90deg * 16 * MBUS(t2) + 2)/360 ~= MBUS * 4
+ or t2, (1 << 14) # set the count direction
+
+ lw t3, DDR_DDR3_4_PHASE_CNTL(t1) # Get current DDR3/4 value.
+ ori t3, 0x7fff # Clear low 15 bits (DDR3 value).
+ xori t3, 0x7fff
+ or t3, t2 # Set new DDR3 value, preserving existing DDR4 value.
+ sw t3, DDR_DDR3_4_PHASE_CNTL(t1)
+
+ li t4, (1 << 28) | (7 << 24) | (1 << 23) | (1 << 20) | (7 << 16) # UBUS_CNTR_CYCLES = 1, LLMB_CNTR_CYCLES = 7, UBUS_CNTR_EN = 1, PH_CNTR_EN = 1, PH_CNTR_CYCLES = 7
+ sw t4, DDR_MIPS_PHASE_CNTL(t1)
+
+ li t4, 0x103e
+ sw t4, DDR_UBUS_PI_DSK1(t1)
+ li t4, 0x40000000
+ sw t4, DDR_UBUS_PI_DSK0(t1)
+
+ ## Set PI mask, and frequnecy of updates
+ # bit[5:0] 1 to 31, controls how often feedback is send back to PI
+ # bit[7] update register in sampling logic to take the new value in bit[5:0]
+ # bit[14:8] masking bits for the sampling result
+
+ li t2, 0x00000010 # 0x8 for 8 DDR cycles, 0x10 for 16 DDR cycles, 0x4 for 4 DDR cycles, can take values from 1 to 31
+ sw t2, DDR_UBUS_PI_DSK0(t1) # set PI update to 16 ddr cycles
+ li t2, 0x00000090 # update value
+ sw t2, DDR_UBUS_PI_DSK0(t1)
+ li t2, 0x00000c90 # set mask to 0001100; 0x1890 will set mask to 0011000
+ sw t2, DDR_UBUS_PI_DSK0(t1)
+
+ ###### Check to see if we found the edge...
+ ###### Ideally we want to loop here until we find an edge....
+
+ li t3, 0
+ li t2, 10000
+
+1:
+ # Looking for a rising edge.
+ lw t4, DDR_UBUS_PI_DSK0(t1) # Read a sample value.
+ srl t4, 16 # The sample is in the upper 16 bits.
+ andi t4, 0x41 # Look at the 2 outermost bits; if the LSB is 0 and the MSB is 1,
+ beq t4, 0x40, 2f # then there is an edge somewhere in the sample.
+
+ addi t3, 1
+ bne t2, t3, 1b
+ nop
+
+2:
+
+ /**----- Configure DDR controller ------------------------------------**/
+ li v0, 16
+ li t2, ((MEMC_12BIT_ROW << MEMC_ROW_SHFT) | (MEMC_9BIT_COL << MEMC_COL_SHFT))
+ or t2, (MEMC_16BIT_BUS << MEMC_WIDTH_SHFT)
+ or t2, (MEMC_SEL_PRIORITY)
+ or t2, (2 << MEMC_EARLY_HDR_CNT_SHFT)
+ or t2, (MEMC_USE_HDR_CNT)
+// or t2, (MEMC_EN_FAST_REPLY)
+ or t2, (MEMC_RR_ARB)
+ or t2, (MEMC_DQS_GATE_EN | MEMC_MEMTYPE_DDR)
+ sw t2, MEMC_CONFIG(t0) # Enable DDR Mem & SEQ EN, 16MB
+
+ li t2, 0x7 # Reduce drive strength for command pins (per John Lorek)
+ sw t2, DDR_CMD_PAD_CNTL(t1)
+
+ li t2, 0x00A778DD
+ sw t2, MEMC_DRAM_TIM(t0) # DDR Timing Set Latency 2.5 Latency,tRAS period =7,tRFC period=12, tWR=3
+ li t2, 0x00000003
+ sw t2, MEMC_CONTROL(t0) # Turn on CKE
+ li t2, 0x0000000B
+ sw t2, MEMC_CONTROL(t0) # PreCharge
+ li t2, 0x00004002
+ sw t2, MEMC_M_EM_BUF(t0) # Value for Extended Mode Register, DDR Reduced Drive Strength On
+ li t2, 0x00000013
+ sw t2, MEMC_CONTROL(t0) # MRS command
+ li t2, 0x00000163
+ sw t2, MEMC_M_EM_BUF(t0) # Reset DLL, Burst Length = 8, Burst Type Sequential 2.5 Latency
+ li t2, 0x00000013
+ sw t2, MEMC_CONTROL(t0) # MRS command
+ nop # Delay 200 DDR clock cycles (~1.5 uS)
+ nop
+ nop
+ li t2, 0x0000000B
+ sw t2, MEMC_CONTROL(t0) # Precharge
+ li t2, 0x0000840f
+ sw t2, MEMC_REF_PD_CONTROL(t0) # Enable auto refresh
+ li t2, 0x00000007
+ sw t2, MEMC_CONTROL(t0) # Set Auto Refresh Mode
+ li t2, 0x00000007
+ sw t2, MEMC_CONTROL(t0) # Set Auto Refresh Mode
+ li t2, 0x00000063
+ sw t2, MEMC_M_EM_BUF(t0) # Reset DLL, Burst Length = 8, Burst Type Sequential 2.5 Latency
+ li t2, 0x00000013
+ sw t2, MEMC_CONTROL(t0) # MRS
+
+ .set reorder
+
+ li sp, 0x80001000
+ sub sp, 8
+ sw ra, 0(sp)
+ sw v0, 4(sp)
+ bal sdramDqsPhaseSet
+ lw v0, 4(sp)
+ lw ra, 0(sp)
+ add sp, 8
+
+ /**----- switch to sync -----------------------------------------**/
+ li t0, 0xff410000
+ li t1, DDR_BASE
+ li t2, 4048
+ li t3, 1
+
+1:
+ lw t4, 0x40(t0) # Read a sample value.
+ srl t4, 16 # The sample is in the upper 16 bits.
+
+ andi t4, t4, 0x41 # Look at the 2 outermost bits; if the LSB is 0 and the MSB is 1,
+ beq t4, 0x40, 2f # then there is an edge somewhere in the sample.
+
+ lw t5, DDR_MIPS_PHASE_CNTL(t1)
+ and t5, 0xffff0000
+ or t5, t3
+ or t5, (1<<14)
+ sw t5, DDR_MIPS_PHASE_CNTL(t1)
+
+ lw t5, 0x40(t0) # Delay before reading another sample.
+ add t3, 1
+ bne t2, t3, 1b
+ b 3f
+
+2:
+ # Success
+ lw t2, DDR_MIPS_PHASE_CNTL(t1) # Turn on auto-PI mode.
+ and t2, 0xf0ffffff
+ or t2, (1 << 24) | (1 << 21) # LLMB_CNTR_CYCLES_CNTL = 1, LLMB_CNTR_EN = 1
+ sw t2, DDR_MIPS_PHASE_CNTL(t1)
+
+ li t2, 0x0010 # Set PI mask to 0000110, and check new value every 16 MIPS cycles.
+ sw t2, 0x40(t0) # set PI update to 16 ddr cycles
+ li t2, 0x80000090 # Enable MIPS auto-PI | Enable update period | Set 16 clock update
+ sw t2, 0x40(t0)
+ li t2, 0x80000c90 # Enable MIPS auto-PI | Enable comparator | Enable update period | Set 16 clock update
+ sw t2, 0x40(t0)
+
+ lw t2, 0x40(t0) # Do a few reads to wait till the edge is stable...
+ lw t2, 0x40(t0)
+ lw t2, 0x40(t0)
+ lw t2, 0x40(t0)
+ lw t2, 0x40(t0)
+
+ mfc0 t1, C0_BCM_CONFIG, 5
+ and t1, ~(0x1 << 28)
+ mtc0 t1, C0_BCM_CONFIG, 5
+
+ /**----- Enable RAC and LMB -------------------------------------**/
+ li t1, MIPS_BASE
+ lw t2, MIPS_LMB_CR(t1)
+ or t2, LMB_EN # Enable LMB
+ sw t2, MIPS_LMB_CR(t1)
+
+ li t2, 0xFFF << RAC_UPB_SHFT # Enable prefetch for RAM address range up to 256MB
+ sw t2, MIPS_RAC_ARR(t1)
+
+ lw t2, MIPS_RAC_CR0(t1)
+ or t2, (RAC_C_INV | RAC_I | RAC_PF_I)
+ sw t2, MIPS_RAC_CR0(t1)
+
+ lw t2, MIPS_RAC_CR1(t1)
+ or t2, (RAC_C_INV | RAC_I | RAC_PF_I)
+ sw t2, MIPS_RAC_CR1(t1)
+
+3:
+ /**----- Enable branch prediction and non-blocking data cache ---**/
+ mfc0 t1, C0_BCM_CONFIG
+ and t1, ~CP0_BCM_CFG_BTHD
+ or t1, CP0_BCM_CFG_NBK
+ or t1, CP0_BCM_CFG_CLF
+ mtc0 t1, C0_BCM_CONFIG
+
+ /* Test whether memory is 16 or 32 bit wide */
+ li t0, MEMC_BASE
+ lw t2, MEMC_CONFIG(t0)
+ and t2, ~MEMC_WIDTH_MASK
+ or t2, (MEMC_32BIT_BUS << MEMC_WIDTH_SHFT)
+ sw t2, MEMC_CONFIG(t0)
+
+ li t3, DRAM_BASE_NOCACHE
+ li t4, 0x12345678
+ sw t4, 0(t3)
+ li t4, 0x87654321
+ sw t4, 4(t3)
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ li t4, 0x12345678
+ lw t5, 0(t3)
+ beq t4, t5, 4f
+
+ /* 16 bit wide memory */
+ lw t2, MEMC_CONFIG(t0)
+ and t2, ~MEMC_WIDTH_MASK
+ or t2, (MEMC_16BIT_BUS << MEMC_WIDTH_SHFT)
+ sw t2, MEMC_CONFIG(t0)
+4:
+ j ra
+
+END(board_draminit)
+
+/* *********************************************************************
+ * BOARD_SETLEDS(x)
+ *
+ * Set LEDs for boot-time progress indication. Not used if
+ * the board does not have progress LEDs. This routine
+ * must not call any other routines, since it may be invoked
+ * either from KSEG0 or KSEG1 and it may be invoked
+ * whether or not the icache is operational.
+ *
+ * Input parameters:
+ * a0 - LED value (8 bits per character, 4 characters)
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * t0,t1,t2,t3
+ ********************************************************************* */
+LEAF(board_setleds)
+#if 0
+ li t0, UART_BASE
+ li t2, TXFIFOEMT
+
+1: lh t1, UART0INTSTAT(t0)
+ and t1, t2
+ bne t1, t2, 1b
+
+ srl t3, a0, 24
+ sb t3, UART0DATA(t0)
+ srl t3, a0, 16
+ sb t3, UART0DATA(t0)
+ srl t3, a0, 8
+ sb t3, UART0DATA(t0)
+ sb a0, UART0DATA(t0)
+ li a0, '\r'
+ sb a0, UART0DATA(t0)
+ li a0, '\n'
+ sb a0, UART0DATA(t0)
+#endif
+ j ra
+END(board_setleds)
+
+/* *********************************************************************
+ * BCMCORE_TP1_SWITCH()
+ *
+ * Check if the thread switch is required. If we are already
+ * running on thread 1 this function will do nothing and just return
+ * If we are running on thread 0 this function will take thread 1
+ * out of reset and put thread 0 to sleep waiting for singnal from
+ * thread 1.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+LEAF(bcmcore_tp1_switch)
+
+ mfc0 t1, C0_BCM_CONFIG, 3
+ li t2, CP0_CMT_TPID
+ and t1, t2
+ bnez t1, tp1 # Already running on thread 1
+
+# Start TP1
+# Set boot address for TP1
+ li t1, MIPS_BASE
+ li t2, 0x98000000 | ENABLE_ALT_BV
+ sw t2, MIPS_TP1_ALT_BV(t1)
+
+# Set a flag so we can wait for TP1 to catch up
+ li t1, 0x0
+ mtc0 t1, $31 # CO_DESAVE
+
+# Take TP1 out of reset
+ mfc0 t1, C0_BCM_CONFIG, 2
+ or t1, CP0_CMT_RSTSE
+ mtc0 t1, C0_BCM_CONFIG, 2
+
+ /* wait until second thread catches up with the first */
+waittp1:
+ mfc0 t0, $31 # CO_DESAVE
+ beqz t0, waittp1
+
+ li t0, THREAD_NUM_ADDRESS
+ FIXUP(t0)
+ lw t0, 0(t0)
+ li t1, 1
+ bne t0, t1, return # Linux will run on TP0, continue running bootloader
+
+# Voice will run on TP0. Set it up and put it to sleep
+
+ # enable interrupts and enable SW IRQ 0
+ li t0, M_SR_IE | M_SR_IBIT1
+ mtc0 t0, C0_SR
+
+ # Set up to use alternate exception vector 0x80000200
+ li t0, M_CAUSE_IV
+ mtc0 t0, C0_CAUSE
+
+ mfc0 t1, C0_BCM_CONFIG, 1
+ # set all ints except IRQ1 to TP1 and cross over SW IRQ 0
+ or t1, (CP0_CMT_XIR_4 | CP0_CMT_XIR_3 | CP0_CMT_XIR_2 | CP0_CMT_XIR_0 | CP0_CMT_SIR_0 | CP0_CMT_NMIR_TP1)
+ mtc0 t1, C0_BCM_CONFIG, 1
+
+ mfc0 t1, C0_BCM_CONFIG, 2
+ # Set debug on TP1, give priority to TP0, and
+ # set TLB exception serialization to ignore SCNT value in CP0 reg22 sel 4
+ and t1, ~CP0_CMT_TPS_MASK;
+ or t1, (CP0_CMT_DSU_TP1 | CP0_CMT_PRIO_TP0 | (1 << CP0_CMT_TPS_SHFT))
+ mtc0 t1, C0_BCM_CONFIG, 2
+
+ # Enable Data RAC on TP0
+ li t1, MIPS_BASE
+ lw t2, MIPS_RAC_CR0(t1)
+ or t2, (RAC_D | RAC_PF_D)
+ sw t2, MIPS_RAC_CR0(t1)
+
+2:
+ li t8, 0
+ b wait_for_wake
+
+tp1:
+# Running on TP1....
+# First signal to TP0 that TP1 is up
+ li t1, 0x1
+ mtc0 t1, $31 # CO_DESAVE
+
+ li t0, THREAD_NUM_ADDRESS
+ FIXUP(t0)
+ lw t0, 0(t0)
+ li t1, 1
+ beq t0, t1, return # Linux will run on TP1, continue running bootloader
+
+# Voice will run on TP1. Set it up and put it to sleep
+
+ # enable interrupts and enable SW IRQ 0
+ li t0, M_SR_IE | M_SR_IBIT1
+ mtc0 t0, C0_SR
+
+ # Set up to use alternate exception vector 0x80000200
+ li t0, M_CAUSE_IV
+ mtc0 t0, C0_CAUSE
+
+ mfc0 t1, C0_BCM_CONFIG, 1
+ # set IRQ1 to TP1 and cross over SW IRQ 0
+ or t1, (CP0_CMT_XIR_1 | CP0_CMT_SIR_0 | CP0_CMT_NMIR_TP0)
+ mtc0 t1, C0_BCM_CONFIG, 1
+
+ mfc0 t1, C0_BCM_CONFIG, 2
+ # Set debug on TP0, give priority to TP1, and
+ # set TLB exception serialization to ignore SCNT value in CP0 reg22 sel 4
+ and t1, ~CP0_CMT_TPS_MASK;
+ or t1, (CP0_CMT_PRIO_TP1 | (1 << CP0_CMT_TPS_SHFT))
+ mtc0 t1, C0_BCM_CONFIG, 2
+
+ # Enable Data RAC on TP1
+ li t1, MIPS_BASE
+ lw t2, MIPS_RAC_CR1(t1)
+ or t2, (RAC_D | RAC_PF_D)
+ sw t2, MIPS_RAC_CR1(t1)
+ b 2b
+
+return:
+ j ra
+
+END(bcmcore_tp1_switch)
+
+# align this code to cache line. NAND flash is not memory mapped after system boots
+# so when we are signaling to the second TP to wake we need
+# jal instruction to be in cache
+ .align 4
+LEAF(wait_for_wake)
+ sync
+ wait # wait for interrupt
+ jal t8 # jump to entry point
+END(wait_for_wake)
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_sdramDqs.c b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_sdramDqs.c
new file mode 100755
index 0000000..96d5000
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm6368_sdramDqs.c
@@ -0,0 +1,439 @@
+/***************************************************************************
+*
+* Copyright (c) 2004 Broadcom Corporation, All Rights Reserved.
+* Contains proprietary and confidential information.
+*
+* No portions of this material may be reproduced in any form without the
+* written permission of:
+*
+* Broadcom Corporation
+* 16215 Alton Parkway
+* P.O. Box 57013
+* Irvine, California 92619-7013
+*
+* All information contained in this document is Broadcom Corporation
+* company private, proprietary, and trade secret.
+*
+****************************************************************************/
+#include "lib_types.h"
+#include "bcm_map.h"
+
+// Uncomment out the below line to use MemoryTestSuite()
+// #define EXTENDED_MEMORY_TESTS
+
+/* ---- Private Constants and Types -------------------------------------- */
+#define VCDL_PHASE_DEFAULT 16
+#define VCDL_PHASE_MAX 47 /* 154.69 degree */
+#define VCDL_PHASE_MIN 0 /* 22.5 degree */
+
+typedef unsigned long u;
+
+#define N 32*1024 // Size of the copy operation
+ // Must be at least equal to the L2 cache size
+#define S (1*sizeof(u))
+
+/* ---- Private Function Prototypes -------------------------------------- */
+inline static int MemoryTest(void) __attribute__((always_inline));
+inline static void PI_upper_set(volatile uint32 *, int bitOffset, int shift) __attribute__((always_inline));
+inline static void PI_shmoo(volatile uint32 *PI_reg, int bitOffset, int minValue, int maxValue, int increment) __attribute__((always_inline));
+inline static void shmooVcdl(int minValue, int maxValue, int increment) __attribute__((always_inline));
+
+// #define DEBUG_SHMOO 1
+#if DEBUG_SHMOO
+inline static void dumpChar(uint8 c) __attribute__((always_inline));
+inline static void dumpChar(uint8 c)
+{
+ //wait till tx fifo below threshold
+ while (UART->txf_levl > 14);
+ UART->Data = c;
+}
+
+#else
+#define dumpChar(c)
+#endif
+
+#if defined(EXTENDED_MEMORY_TESTS)
+#include "memtest.c"/* Suite memory tests SCAN, MARCH, SLIDING, SHIFT ADDRESS */
+inline static int MemoryTestSuite(void) __attribute__((always_inline));
+#endif
+
+/* ==== Public Functions ================================================= */
+void sdramDqsPhaseSet(void);
+void vcdlCalibration(void);
+
+/*******************************************************************************/
+void sdramDqsPhaseSet(void)
+{
+ int dqOutPhaseMax;
+ int delay;
+ int ubusPhase, mipsPhase;
+ int equalCount = 0;
+
+ // Reset VCDL
+ DDR->Spare1 |= 0x1;
+ delay = 1000;
+ while(delay--);
+ DDR->Spare1 &= ~0x1;
+
+ // Calculate max phase offset from PLL config register.
+ dqOutPhaseMax = ((DDR->MIPSDDRPLLMDiv & DDR_MDIV_MASK) >> DDR_MDIV_SHFT) * 8;
+
+ dumpChar('\n');
+ dumpChar('\r');
+
+ // Start by setting VCDL to the default. This almost always works.
+ // Enable squelch
+ DDR->WSliceCntl |= (0x1<<20) | (0x1<<4);
+ DDR->VCDLPhaseCntl0 = (VCDL_PHASE_DEFAULT << 22) | (VCDL_PHASE_DEFAULT << 16) | (VCDL_PHASE_DEFAULT << 6) | VCDL_PHASE_DEFAULT;
+ DDR->VCDLPhaseCntl1 = (VCDL_PHASE_DEFAULT << 22) | (VCDL_PHASE_DEFAULT << 16) | (VCDL_PHASE_DEFAULT << 6) | VCDL_PHASE_DEFAULT;
+ DDR->WSliceCntl &= ~((0x1<<20) | (0x1<<4));
+
+ // Now shmoo over DQ phase to find an optimum value.
+ dumpChar('D');dumpChar('D');dumpChar('R');dumpChar('2');
+ dumpChar('\n');
+ dumpChar('\r');
+ PI_shmoo(&DDR->DDR1_2PhaseCntl0, 16, -dqOutPhaseMax, dqOutPhaseMax, 1);
+
+ dumpChar('V');dumpChar('C');dumpChar('D');dumpChar('L');
+ dumpChar('\n');
+ dumpChar('\r');
+ shmooVcdl(VCDL_PHASE_MIN, VCDL_PHASE_MAX, 1);
+
+ // Now setup the UBUS clock
+ dumpChar('U');dumpChar('B');dumpChar('U');dumpChar('S');
+ dumpChar('\n');
+ dumpChar('\r');
+
+ MEMC->RefreshPdControl &= ~MEMC_REFRESH_ENABLE; // Turn off refresh while messing with UBus clock
+
+ DDR->MIPSPhaseCntl &= ~(0x1<<23); // turn off ubus PI auto mode
+
+ mipsPhase = DDR->MIPSPhaseCntl;
+ do {
+ if (DDR->MIPSPhaseCntl == mipsPhase)
+ equalCount++;
+ else {
+ equalCount = 0;
+ mipsPhase = DDR->MIPSPhaseCntl;
+ }
+ } while (equalCount < 3);
+
+ ubusPhase = ((DDR->UBUSPhaseCntl) & 0x3ffe); // make it even and decrease count
+ DDR->UBUSPhaseCntl = ubusPhase;
+
+ // Wait until we match several times in a row, to be sure we wait long enough
+ do {
+ if (DDR->UBUSPhaseCntl == ubusPhase)
+ equalCount++;
+ else
+ equalCount = 0;
+ } while (equalCount < 3);
+
+ MEMC->RefreshPdControl |= MEMC_REFRESH_ENABLE;
+}
+
+
+/* ==== Private Functions ================================================ */
+
+inline static void PI_upper_set(volatile uint32 *PI_reg, int bitOffset, int shift)
+{
+ uint32 oldVal;
+ uint32 newVal;
+ int32 oldPhase;
+ int32 newPhase;
+ int equalCount = 0;
+
+ oldVal = *PI_reg; // get the phase config (may have other controls in other 16 bits)
+
+ oldPhase = ( oldVal >> bitOffset ) & 0x3fff;
+ if ( oldPhase & (0x1<<13) ) {
+ oldPhase |= ~0x3fff; // sign extend
+ }
+
+ newPhase = shift & 0x3fff; // set up phase shift value[13:0]
+ if (shift > oldPhase) { // set up up/down [14], shift is signed value
+ newPhase |= 0x1<<14;
+ }
+
+ newPhase = newPhase << bitOffset;
+ oldVal = oldVal & (0xffff << (16-bitOffset)); // Keep the other control bits
+ newVal = newPhase | oldVal;
+ *PI_reg = newVal;
+
+ // Wait until we match several times in a row, to be sure we wait long enough
+ do {
+ if (*PI_reg == newVal)
+ equalCount++;
+ else
+ equalCount = 0;
+ } while (equalCount < 3);
+}
+
+
+inline static void PI_shmoo(volatile uint32 *PI_reg, int bitOffset, int minValue, int maxValue, int increment)
+{
+ int piPhase, piPhaseCnt, passStatus;
+ int pass1Start, pass1Fail, pass2Start, pass2Fail;
+ int pass1Cnt, pass2Cnt;
+
+ PI_upper_set(PI_reg, bitOffset, minValue);
+
+ passStatus = 0;
+ pass1Start = maxValue;
+ pass1Fail = minValue;
+ pass2Start = minValue;
+ pass2Fail = minValue;
+
+ for (piPhase = minValue; piPhase <= maxValue; piPhase += increment) {
+
+ // if (MemoryTestSuite())
+ if (MemoryTest())
+ {
+ if (passStatus == 0x0) { // first_pass start
+ passStatus = 0x1;
+ pass1Start = piPhase;
+ }
+ else if (passStatus == 0x2) { // second_pass start
+ passStatus = 0x3;
+ pass2Start = piPhase;
+ }
+ dumpChar('p');
+ }
+ else {
+ if (passStatus == 0x1) { // fisrt_pass end
+ passStatus = 0x2;
+ pass1Fail = piPhase;
+ }
+ else if (passStatus == 0x3) { // second_pass end
+ passStatus = 0x4;
+ pass2Fail = piPhase;
+ }
+ dumpChar('.');
+ }
+
+ piPhaseCnt = ( piPhase + 0x01) & 0x3fff;
+ if (increment) {
+ piPhaseCnt |= (0x01<<14);
+ }
+
+ *PI_reg = (*PI_reg & (0xffff << (16-bitOffset))) | (piPhaseCnt<<bitOffset);
+
+ }
+
+ // Figure out the middle point of the pass window
+ // valid window 1 -- .......PPPPPPPPPPPPPP.......
+ // valid window 2 -- PPPPPPP........PPPPPPPPPPPPP
+
+ if ((pass1Start != maxValue) && (pass2Start == minValue)) { // valid window 1
+ if (pass1Fail == minValue) {
+ piPhaseCnt = (pass1Start + maxValue) >> 1; // mid-point of the pass window
+ } else {
+ piPhaseCnt = (pass1Start + pass1Fail - 0x1) >> 1; // mid-point of the pass window
+ }
+ }
+ else if ((pass1Start == minValue) && (pass2Start != minValue) && (pass2Fail == minValue)) { // valid window 2
+ pass1Cnt = pass1Fail - minValue;
+ pass2Cnt = maxValue - pass2Start + 1;
+ passStatus= (pass1Cnt + pass2Cnt) >> 1;
+ if (passStatus < pass1Cnt) { // mid-point of the overall pass window is in sub-window 1
+ piPhaseCnt = minValue + ( pass1Cnt - passStatus );
+ }
+ else {
+ piPhaseCnt = pass2Start - 0x1 + passStatus;
+ }
+ }
+ else {
+ piPhaseCnt = 0x0; // shmoo failed.
+ }
+
+ piPhaseCnt &= ~0x01; // make it even number
+
+ PI_upper_set(PI_reg, bitOffset, piPhaseCnt); // set the final phase value
+
+ dumpChar('\n');
+ dumpChar('\r');
+}
+
+
+inline static void shmooVcdl(int minValue, int maxValue, int increment)
+{
+ UINT32 dqsInPhase;
+ UINT32 dqsInSum = 0;
+ UINT32 passCnt = 0;
+ volatile int delay;
+
+ for (dqsInPhase = minValue; dqsInPhase <= maxValue; dqsInPhase += increment) {
+ delay = 1000;
+ while(delay--);
+ // Enable squelch
+ DDR->WSliceCntl |= (0x1<<20) | (0x1<<4);
+ DDR->VCDLPhaseCntl0 = (dqsInPhase << 22) | (dqsInPhase << 16) | (dqsInPhase << 6) | dqsInPhase;
+ DDR->VCDLPhaseCntl1 = (dqsInPhase << 22) | (dqsInPhase << 16) | (dqsInPhase << 6) | dqsInPhase;
+ DDR->WSliceCntl &= ~((0x1<<20) | (0x1<<4));
+
+ delay = 1000;
+ while(delay--);
+
+#if defined(EXTENDED_MEMORY_TESTS)
+ if (MemoryTestSuite() == MEMTEST_SUCCESS )
+#else
+ if (MemoryTest())
+#endif
+ {
+ dqsInSum += dqsInPhase;
+ passCnt++;
+ dumpChar('p');
+ }
+ else {
+ dumpChar('.');
+ }
+ }
+ delay = 1000;
+ while(delay--);
+ // Enable squelch
+ DDR->WSliceCntl |= (0x1<<20) | (0x1<<4);
+ if (passCnt > 0) {
+ dqsInPhase = dqsInSum / passCnt;
+ DDR->VCDLPhaseCntl0 = (dqsInPhase << 22) | (dqsInPhase << 16) | (dqsInPhase << 6) | dqsInPhase;
+ DDR->VCDLPhaseCntl1 = (dqsInPhase << 22) | (dqsInPhase << 16) | (dqsInPhase << 6) | dqsInPhase;
+ }
+ else {
+ DDR->VCDLPhaseCntl0 = (VCDL_PHASE_DEFAULT << 22) | (VCDL_PHASE_DEFAULT << 16) | (VCDL_PHASE_DEFAULT << 6) | VCDL_PHASE_DEFAULT;
+ DDR->VCDLPhaseCntl1 = (VCDL_PHASE_DEFAULT << 22) | (VCDL_PHASE_DEFAULT << 16) | (VCDL_PHASE_DEFAULT << 6) | VCDL_PHASE_DEFAULT;
+ }
+ DDR->WSliceCntl &= ~((0x1<<20) | (0x1<<4));
+ dumpChar('\n');
+ dumpChar('\r');
+}
+
+#if defined(EXTENDED_MEMORY_TESTS)
+
+// Define the memory size for use by the memory test suite
+#define MEMORY_SIZE (2 * 1024)
+
+int MemoryTestSuite(void)
+{
+ int test = 1;
+ uint32_t * memory = (uint32_t*) (0xa0000000);
+ Pattern_t pat32, patIx;
+
+ for (patIx = PATTERN_0x00000000; patIx < PATTERN_MAX; patIx++ )
+ {
+ pat32 = pattern[ patIx ];
+
+ fill_memory( memory, MEMORY_SIZE, 0x0 );
+ if ( scanWordValue( memory, MEMORY_SIZE, pat32 ) == MEMTEST_FAILURE )
+ goto exit_tests;
+
+ test++;
+
+ fill_memory( memory, MEMORY_SIZE, 0x0 );
+ if ( scanBulkValue( memory, MEMORY_SIZE, pat32 ) == MEMTEST_FAILURE )
+ goto exit_tests;
+
+ test++;
+
+ fill_memory( memory, MEMORY_SIZE, 0x0 );
+ if ( scanBulkAltInv( memory, MEMORY_SIZE, pat32 ) == MEMTEST_FAILURE )
+ goto exit_tests;
+
+ test++;
+
+ fill_memory( memory, MEMORY_SIZE, 0x0 );
+ if ( slidingAltInv( memory, MEMORY_SIZE, pat32 ) == MEMTEST_FAILURE )
+ goto exit_tests;
+
+ test++;
+
+ fill_memory( memory, MEMORY_SIZE, 0x0 );
+ if ( slidingDiag( memory, MEMORY_SIZE, pat32 ) == MEMTEST_FAILURE )
+ goto exit_tests;
+
+ test++;
+ }
+
+ fill_memory( memory, MEMORY_SIZE, 0x0 );
+ if ( scanWordSelf( memory, MEMORY_SIZE ) == MEMTEST_FAILURE )
+ goto exit_tests;
+
+ test++;
+
+ fill_memory( memory, MEMORY_SIZE, 0x0 );
+ if ( scanBulkSelf( memory, MEMORY_SIZE ) == MEMTEST_FAILURE )
+ goto exit_tests;
+
+ test++;
+
+ fill_alt_memory( memory, MEMORY_SIZE, 0XAAAAAAAA, 0x55555555 );
+ if ( memoryBulkCopy( memory, (memory + ((MEMORY_SIZE/2)/sizeof(uint32_t))),
+ MEMORY_SIZE/2 ) == MEMTEST_FAILURE )
+ goto exit_tests;
+
+ // return tests;
+ return MEMTEST_SUCCESS;
+
+exit_tests:
+ return MEMTEST_FAILURE;
+
+}
+#endif /* defined(EXTENDED_MEMORY_TESTS) */
+
+//
+// Returns: 0=FAILURE, 1=SUCCESS
+inline static int MemoryTest(void)
+{
+ // Test 32-bit write/read
+ volatile uint32 *memAddr;
+ uint32 memBase;
+ uint32 testValue;
+ int i;
+ int j;
+ int k;
+
+ memBase = 0xa0000000;
+ for (i = 2; i < 24; i++) {
+ memAddr = (void *) (memBase + (1 << i));
+ for (k = 0; k < 2; k++) {
+ /* walking one */
+ testValue = 1;
+ for (j = 0; j < 32; j++) {
+ *memAddr = testValue;
+ if (*memAddr != testValue)
+ return 0;
+
+ testValue <<= 1;
+ }
+ /* walking zero */
+ testValue = ~1;
+ for (j = 0; j < 32; j++) {
+ *memAddr = testValue;
+ if (*memAddr != testValue)
+ return 0;
+
+ testValue = (testValue << 1) | 1;
+ }
+ /* shift in zeroes */
+ testValue = -1;
+ for (j = 0; j < 32; j++) {
+ *memAddr = testValue;
+ *(uint32*)memBase = 0;
+ if (*memAddr != testValue)
+ return 0;
+
+ testValue <<= 1;
+ }
+ /* shift in ones */
+ testValue = 1;
+ for (j = 0; j < 32; j++) {
+ *memAddr = testValue;
+ *(uint32*)memBase = 0;
+ if (*memAddr != testValue)
+ return 0;
+
+ testValue = (testValue << 1) | 1;
+ }
+ }
+ }
+ return 1;
+}
+
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_impl1_rom_boot.S b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_impl1_rom_boot.S
new file mode 100755
index 0000000..b3986ed
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_impl1_rom_boot.S
@@ -0,0 +1,1818 @@
+#include "sbmips.h"
+#include "bsp_config.h"
+
+#include "bcm_cpu.h"
+#include "bcm_common.h"
+
+#include "bcm_hwdefs.h"
+#include "boardparms.h"
+#include "mipsmacros.h"
+
+#define DDR_TEST 1
+#define UBUS_SYNC_ENABLE 1
+#define LMB_SYNC_ENABLE 1
+#define MIPS_SYNC_ENABLE 1
+#define LMB_ENABLE 1
+
+/* Memory mapping table for different size DRAMs (256Mb, 512Mb, 1Gb, 2Gb) */
+ .globl dram_map_table_x8
+dram_map_table_x8:
+ // 128Mb 64B Interleaving (x8 Mode) 32MB
+ // This is just a place holder. This memory does not exist
+ _LONG_ 0x0F0E0D0C, 0x13121110, 0x17161514, 0x00000018 // Row00_0 Row00_1 Row01_0 Row01_1
+ _LONG_ 0x04000000, 0x0A090805, 0x0000000B, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1
+ _LONG_ 0x00080706, 0x00000002, 0x00000055 // Bank CS_End Dramsize
+
+ // 256Mb 64B Interleaving (x8 Mode) 64MB
+ _LONG_ 0x100F0E0D, 0x14131211, 0x18171615, 0x00000019 // Row00_0 Row00_1 Row01_0 Row01_1
+ _LONG_ 0x04000000, 0x0A090805, 0x00000C0B, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1
+ _LONG_ 0x00000706, 0x00000004, 0x00000066 // Bank CS_End Dramsize
+
+ // 512Mb 64B Interleaving (x8 Mode) 128MB
+ _LONG_ 0x100F0E0D, 0x14131211, 0x18171615, 0x00001A19 // Row00_0 Row00_1 Row01_0 Row01_1
+ _LONG_ 0x04000000, 0x0A090805, 0x00000C0B, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1
+ _LONG_ 0x00000706, 0x00000008, 0x00000077 // Bank CS_End Dramsize
+
+ // 1Gb 64B Interleaving (x8 Mode) 256MB
+ _LONG_ 0x11100F0E, 0x15141312, 0x19181716, 0x00001B1A // Row00_0 Row00_1 Row01_0 Row01_1
+ _LONG_ 0x04000000, 0x0B0A0905, 0x00000D0C, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1
+ _LONG_ 0x00080706, 0x00000010, 0x00000088 // Bank CS_End Dramsize
+
+ .globl dram_map_table_x16
+dram_map_table_x16:
+ // 256Mb 64B Interleaving (x16 Mode) 32MB
+ _LONG_ 0x0F0E0D0C, 0x13121110, 0x17161514, 0x00000018 // Row00_0 Row00_1 Row01_0 Row01_1
+ _LONG_ 0x04000000, 0x0A090805, 0x0000000B, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1
+ _LONG_ 0x00000706, 0x00000002, 0x00000055 // Bank CS_End Dramsize
+
+ // 512Mb 64B Interleaving (x16 Mode) 64MB
+ _LONG_ 0x100F0E0D, 0x14131211, 0x18171615, 0x00000019 // Row00_0 Row00_1 Row01_0 Row01_1
+ _LONG_ 0x04000000, 0x0A090805, 0x00000C0B, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1
+ _LONG_ 0x00000706, 0x00000004, 0x00000066 // Bank CS_End Dramsize
+
+ // 1Gb 64B Interleaving (x16 Mode) 128MB
+ _LONG_ 0x11100F0E, 0x15141312, 0x19181716, 0x0000001A // Row00_0 Row00_1 Row01_0 Row01_1
+ _LONG_ 0x04000000, 0x0B0A0905, 0x00000D0C, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1
+ _LONG_ 0x00080706, 0x00000008, 0x00000077 // Bank CS_End Dramsize
+
+ // 2Gb 64B Interleaving (x16 Mode) 256MB
+ _LONG_ 0x11100F0E, 0x15141312, 0x19181716, 0x00001B1A // Row00_0 Row00_1 Row01_0 Row01_1
+ _LONG_ 0x04000000, 0x0B0A0905, 0x00000D0C, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1
+ _LONG_ 0x00080706, 0x00000010, 0x00000088 // Bank CS_End Dramsize
+
+ .globl dram_tRefi_table
+dram_tRefi_table: /* Refresh Interval table for different Speed DRAMs (100-200, 300-333, 400) */
+ _LONG_ 0x16, 0x49, 0x5D // 100-200 300-333 400 (MHz)
+
+ .globl dram_tRFC_table
+dram_tRFC_table: /* tRFC table for different size & Speed DRAMs (256Mb, 512Mb, 1Gb)/(200, 333, 400) */
+// 200 333 400 (MHz)
+ _LONG_ 0xF, 0x19, 0x1E // 256Mb
+ _LONG_ 0x15, 0x23, 0x2A // 512Mb
+ _LONG_ 0x1A, 0x2B, 0x33 // 1Gb
+ _LONG_ 0x28, 0x42, 0x4F // 2Gb
+
+ .globl dram_timing_table
+dram_timing_table: /* */
+// tRCD tCL tWR tWL tRP tRRD tRC tFAW tW2R tR2W tR2R tAL tRTP tW2W
+// ---------------------------------------------------------------------
+ .byte 0x03,0x04,0x03,0x03,0x03,0x02,0x11,0x00,0x01,0x01,0x00,0x02,0x02,0x00,0x00,0x00 // 200MHz
+ .byte 0x05,0x05,0x05,0x04,0x05,0x04,0x13,0x00,0x02,0x01,0x00,0x04,0x03,0x00,0x00,0x00 // 300MHz
+ .byte 0x05,0x05,0x06,0x04,0x06,0x05,0x18,0x00,0x02,0x01,0x00,0x04,0x03,0x00,0x00,0x00 // 400MHz
+
+ .globl dram_sync_table
+dram_sync_table: /* Bit vector table for Ubus sync modes and Lmb sync modes */
+#if defined(_BCM96328_)
+ _LONG_ 0x8E10FFFF, 0x8A10FFFF, 0xEDC2FFFF // UBUS Sync , LMB Sync, Mips Sync
+#elif defined(_BCM96362_)
+ _LONG_ 0xFFBFBFBF, 0x6341C101, 0xE7E5E5E5 // UBUS Sync , LMB Sync, Mips Sync
+#elif defined(_BCM96816_)
+ _LONG_ 0xC03033B5, 0x80303095, 0xFF90FFFF // UBUS Sync , LMB Sync, Mips Sync
+#endif
+ .globl dram_speed_table
+dram_speed_table: /* Memory Speed Table for different clock strap values */
+ /* 0=200Mhz 1=333MHz 2=400MHz */
+#if defined(_BCM96328_)
+ .byte 0 // 0x0
+ .byte 0 // 0x1
+ .byte 0 // 0x2
+ .byte 0 // 0x3
+ .byte 0 // 0x4
+ .byte 0 // 0x5
+ .byte 0 // 0x6
+ .byte 0 // 0x7
+ .byte 0 // 0x8
+ .byte 0 // 0x9
+ .byte 0 // 0xa
+ .byte 0 // 0xb
+ .byte 0 // 0xc
+ .byte 0 // 0xd
+ .byte 0 // 0xe
+ .byte 0 // 0xf
+ .byte 0 // 0x10
+ .byte 0 // 0x11
+ .byte 0 // 0x12
+ .byte 0 // 0x13
+ .byte 0 // 0x14
+ .byte 0 // 0x15
+ .byte 2 // 0x16
+ .byte 2 // 0x17
+ .byte 0 // 0x18
+ .byte 0 // 0x19
+ .byte 0 // 0x1a
+ .byte 0 // 0x1b
+ .byte 0 // 0x1c
+ .byte 0 // 0x1d
+ .byte 0 // 0x1e
+ .byte 1 // 0x1f
+#elif defined(_BCM96362_)
+ .byte 1 // 0x0
+ .byte 2 // 0x1
+ .byte 0 // 0x2
+ .byte 1 // 0x3
+ .byte 0 // 0x4
+ .byte 2 // 0x5
+ .byte 2 // 0x6
+ .byte 1 // 0x7
+ .byte 1 // 0x8
+ .byte 2 // 0x9
+ .byte 0 // 0xa
+ .byte 1 // 0xb
+ .byte 0 // 0xc
+ .byte 2 // 0xd
+ .byte 2 // 0xe
+ .byte 1 // 0xf
+ .byte 1 // 0x10
+ .byte 2 // 0x11
+ .byte 0 // 0x12
+ .byte 1 // 0x13
+ .byte 0 // 0x14
+ .byte 1 // 0x15 // 267MHz. Need to change tREFI if this is used.
+ .byte 2 // 0x16
+ .byte 1 // 0x17
+ .byte 1 // 0x18
+ .byte 1 // 0x19
+ .byte 0 // 0x1a
+ .byte 1 // 0x1b
+ .byte 0 // 0x1c
+ .byte 0 // 0x1d
+ .byte 2 // 0x1e
+ .byte 1 // 0x1f
+#elif defined(_BCM96816_)
+ .byte 0 // 0x0
+ .byte 1 // 0x1
+ .byte 0 // 0x2
+ .byte 0 // 0x3
+ .byte 0 // 0x4
+ .byte 1 // 0x5
+ .byte 1 // 0x6
+ .byte 1 // 0x7
+ .byte 1 // 0x8
+ .byte 1 // 0x9
+ .byte 1 // 0xa
+ .byte 2 // 0xb
+ .byte 2 // 0xc
+ .byte 2 // 0xd
+ .byte 2 // 0xe
+ .byte 2 // 0xf
+ .byte 2 // 0x10
+ .byte 2 // 0x11
+ .byte 2 // 0x12
+ .byte 2 // 0x13
+ .byte 2 // 0x14
+ .byte 0 // 0x15
+ .byte 0 // 0x16
+ .byte 1 // 0x17
+ .byte 1 // 0x18
+ .byte 1 // 0x19
+ .byte 1 // 0x1a
+ .byte 1 // 0x1b
+ .byte 2 // 0x1c
+ .byte 2 // 0x1d
+ .byte 2 // 0x1e
+ .byte 2 // 0x1f
+#endif
+
+ .globl memc_ubus_ratio_table
+memc_ubus_ratio_table: /* Memory Speed Table for different clock strap values */
+#if defined(_BCM96328_)
+// 6328 Clock Speed Table
+ .byte 3 // 0x0
+ .byte 3 // 0x1
+ .byte 3 // 0x2
+ .byte 3 // 0x3
+ .byte 3 // 0x4
+ .byte 3 // 0x5
+ .byte 3 // 0x6
+ .byte 3 // 0x7
+ .byte 3 // 0x8
+ .byte 3 // 0x9
+ .byte 3 // 0xa
+ .byte 3 // 0xb
+ .byte 3 // 0xc
+ .byte 3 // 0xd
+ .byte 3 // 0xe
+ .byte 3 // 0xf
+ .byte 3 // 0x10
+ .byte 3 // 0x11
+ .byte 0xf // 0x12
+ .byte 0xf // 0x13
+ .byte 3 // 0x14
+ .byte 9 // 0x15
+ .byte 9 // 0x16
+ .byte 9 // 0x17
+ .byte 3 // 0x18
+ .byte 3 // 0x19
+ .byte 3 // 0x1a
+ .byte 3 // 0x1b
+ .byte 0xb // 0x1c
+ .byte 0xb // 0x1d
+ .byte 0xb // 0x1e
+ .byte 3 // 0x1f
+#elif defined(_BCM96362_)
+// 6362 Clock Speed Table
+ .byte 3 // 0x0
+ .byte 3 // 0x1
+ .byte 3 // 0x2
+ .byte 3 // 0x3
+ .byte 3 // 0x4
+ .byte 3 // 0x5
+ .byte 3 // 0x6
+ .byte 3 // 0x7
+ .byte 3 // 0x8
+ .byte 3 // 0x9
+ .byte 3 // 0xa
+ .byte 3 // 0xb
+ .byte 3 // 0xc
+ .byte 3 // 0xd
+ .byte 3 // 0xe
+ .byte 3 // 0xf
+ .byte 3 // 0x10
+ .byte 3 // 0x11
+ .byte 3 // 0x12
+ .byte 3 // 0x13
+ .byte 4 // 0x14
+ .byte 4 // 0x15
+ .byte 15 // 0x16
+ .byte 3 // 0x17
+ .byte 3 // 0x18
+ .byte 3 // 0x19
+ .byte 3 // 0x1a
+ .byte 3 // 0x1b
+ .byte 3 // 0x1c
+ .byte 3 // 0x1d
+ .byte 3 // 0x1e
+ .byte 3 // 0x1f
+#elif defined(_BCM96816_)
+// 6816 Clock Speed Table
+ .byte 3 // 0x0
+ .byte 9 // 0x1
+ .byte 3 // 0x2
+ .byte 4 // 0x3
+ .byte 3 // 0x4
+ .byte 3 // 0x5
+ .byte 9 // 0x6
+ .byte 3 // 0x7
+ .byte 3 // 0x8
+ .byte 3 // 0x9
+ .byte 2 // 0xa
+ .byte 4 // 0xb
+ .byte 2 // 0xc
+ .byte 3 // 0xd
+ .byte 4 // 0xe
+ .byte 9 // 0xf
+ .byte 1 // 0x10
+ .byte 1 // 0x11
+ .byte 1 // 0x12
+ .byte 1 // 0x13
+ .byte 3 // 0x14
+ .byte 3 // 0x15
+ .byte 4 // 0x16
+ .byte 9 // 0x17
+ .byte 6 // 0x18
+ .byte 2 // 0x19
+ .byte 6 // 0x1a
+ .byte 2 // 0x1b
+ .byte 4 // 0x1c
+ .byte 3 // 0x1d
+ .byte 4 // 0x1e
+ .byte 3 // 0x1f
+#endif
+
+#if defined(_BCM96816_)
+ .globl periph_fix_table
+periph_fix_table: // Periph Clock fix vector for different clock strap values
+ _LONG_ 0xAA30A047
+#endif
+
+#define SETLEDS1(a,b,c,d) \
+ li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \
+ bal board_setleds; \
+ nop
+
+/* *********************************************************************
+ * BOARD_EARLYINIT()
+ *
+ * Initialize board registers. This is the earliest
+ * time the BSP gets control. This routine cannot assume that
+ * memory is operational, and therefore all code in this routine
+ * must run from registers only. The $ra register must not
+ * be modified, as it contains the return address.
+ *
+ * This routine will be called from uncached space, before
+ * the caches are initialized. If you want to make
+ * subroutine calls from here, you must use the CALLKSEG1 macro.
+ *
+ * Among other things, this is where the GPIO registers get
+ * programmed to make on-board LEDs function, or other startup
+ * that has to be done before anything will work.
+ *
+ * Input parameters:
+ * a0 - Flash base address (address of MIPS reset)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(board_earlyinit)
+
+ .set noreorder
+
+ mfc0 t1, C0_BCM_CONFIG, 3
+ li t2, CP0_CMT_TPID
+ and t1, t2
+ bnez t1, 3f # if we are running on thread 1, skip init
+ nop
+
+ /**-------------------------------------------------------------**/
+ /** platform specific code **/
+ /**-------------------------------------------------------------**/
+
+#if defined(_BCM96816_)
+ /**----- Offset UBUS Clock 180 degrees -------------------------**/
+ li t2, MISC_BASE
+ lw t1, MISC_STRAP_BUS(t2)
+
+ srl t1, MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT
+ andi t1, 0x1f // Mask out strap bits
+
+ move s0,ra
+ LOADREL(t2, periph_fix_table)
+ lw t2, 0(t2)
+ srl t2, t1
+ andi t2, 1
+ move ra,s0
+
+ beq t2, zero, 2f
+ nop
+
+ li t0, DDR_BASE
+ li t1, 0x00070000 // send new phase value to PLL every 8 cycles
+ sw t1, DDR_CTL_PI_UBUS_CTL(t0)
+ ori t1, 0x4080 // shift 128 steps in the positive direction to be 180 degree's offset VCO 1.6GHz
+ sw t1, DDR_CTL_PI_UBUS_CTL(t0)
+ li t1, 0x00000001
+ sw t1, DDR_CTL_PI_GCF(t0)
+
+ li t1, 0x10000 // delay
+1:
+ bnez t1, 1b
+ addi t1, -1
+
+2:
+ /**----- Set 1.2V and 2.5V Voltage regulators ------------------**/
+ li t1, GPIO_BASE
+ lw t2, GPIO_SWREG_CONFIG(t1)
+ and t2, ~GPIO_SW_VREG_SEL_MASK
+ or t2, (0x0 << GPIO_SW_VREG_SEL_SHIFT)
+ and t2, ~GPIO_LIN_VREG_ADJ_MASK
+ or t2, (0x0 << GPIO_LIN_VREG_ADJ_SHIFT)
+ sw t2, GPIO_SWREG_CONFIG(t1)
+
+ li t1, 0x10000
+1:
+ bnez t1, 1b
+ addi t1, -1
+#endif
+
+#if defined (_BCM96328_) || defined (_BCM96362_)
+ /* slow down mips clk (div 4) to unlock memory */
+ mfc0 t1, C0_BCM_CONFIG, 5
+ or t2, t1, 0x40000000
+ mtc0 t2, C0_BCM_CONFIG, 5
+ nop
+
+ mtc0 t1, C0_BCM_CONFIG, 5
+ nop
+#endif
+
+#if defined (_BCM96362_)
+ /* Adjust VREG frequency up by 50% to improve DSL performance */
+ li t2, MISC_BASE
+
+ /* First set ramp control */
+ lw t1, MISC_VREG_CONTROL0(t2)
+ or t1, (0x2 << MISC_VREG_CONTROL0_VREG_RAMP1P8_SHIFT) | (0x2 << MISC_VREG_CONTROL0_VREG_RAMP1P2_SHIFT)
+ sw t1, MISC_VREG_CONTROL0(t2)
+
+ /* wait 10ms for the setting to take effect */
+ li t8, -2000000
+ mtc0 t8, C0_COUNT
+1:
+ bltz t8, 1b
+ mfc0 t8, C0_COUNT
+
+ and t1, ~((0x7 << MISC_VREG_CONTROL0_VREG_RAMP1P8_SHIFT) | (0x7 << MISC_VREG_CONTROL0_VREG_RAMP1P2_SHIFT))
+ or t1, (0x3 << MISC_VREG_CONTROL0_VREG_ADJ_SHIFT)
+ sw t1, MISC_VREG_CONTROL0(t2)
+
+ /* Increase 2.5V regulator to provide increased range for 1.8V */
+ lw t1, MISC_VREG_CONTROL1(t2)
+ and t1, ~MISC_VREG_CONTROL1_VREG_ISEL2P5_MASK
+ or t1, (MISC_VREG_LDO_2P61 << MISC_VREG_CONTROL1_VREG_ISEL2P5_SHIFT)
+ sw t1, MISC_VREG_CONTROL1(t2)
+#endif
+
+#if 0
+ /* wait for a while to allow catch by jtag debugger */
+ li t8, -(200000000*3) /* we will count up to 0 to delay a couple of seconds */
+ /* and give the emulator a chance to catch us */
+ mtc0 t8, C0_COUNT
+catchloop:
+ bltz t8, catchloop
+ mfc0 t8, C0_COUNT
+#endif
+
+ /**----- Enable I Cache -----------------------------------------**/
+ mfc0 t1, C0_BCM_CONFIG
+ or t1, (CP0_BCM_CFG_ICSHEN | CP0_BCM_CFG_DCSHEN)
+ mtc0 t1, C0_BCM_CONFIG # Enable I Cache
+
+ // In the begining MIPS core registers are mapped to 0xbfax_xxxx
+ li t1, 0x1FA0000C # Set up CBR to 1FAx_xxxx
+ mtc0 t1, C0_BCM_CONFIG, 6
+
+ li t1, MIPS_BASE_BOOT
+ lw t2, MIPS_LMB_CR(t1)
+ or t2, 0xC0000000 # enable ffxx_xxxx space
+ sw t2, MIPS_LMB_CR(t1)
+ li t2, 0xFFF80001 # SBR FFF8_xxxx and enable
+ sw t2, MIPS_SBR(t1)
+
+ // Now map MIPS core registers to 0xFF4x_xxxx space
+ li t1, 0xFF40000C # CBR FF4x_xxxx (and reserved bits 0xc).
+ mtc0 t1, C0_BCM_CONFIG, 6
+
+#if defined(_BCM96816_)
+ /**----- Initialize EBI -----------------------------------------**/
+ li t1, MPI_BASE
+ li t2, EBI_SIZE_32M
+ or t2, a0
+ sw t2, CS0BASE(t1) # CS[0] Base
+ li t2, THREEWT|EBI_WORD_WIDE|EBI_ENABLE
+ sw t2, CS0CNTL(t1) # CS[0] Control
+#endif
+
+ /**----- Initialize Serial --------------------------------------**/
+ li t3, ((FPERIPH / 115200) / 16)
+ /*
+ # Baudword = (FPeriph)/Baud/32-1. We have to perform rounding
+ # and subtraction. Above we divided by 16 (instead of 32). If
+ # bit0 is set, we round up. However, we then subtract 1, so final
+ # result should be t3/2. If bit0 is 0, then we truncate and subtract
+ # 1, t3=t3/2-1.
+ */
+ andi t0, t3, 0x1
+ bne t0,zero,1f # do shift only (in delay slot)
+ # and jump to apply
+ srl t3,1 # do divide by 2
+ addiu t3, -1 # subtract 1
+1:
+
+ // t3 contains the UART BAUDWORD
+ li t0, UART_BASE
+ sw t3, UART0BAUD(t0) # Store BaudRate
+ li t1, BITS8SYM|ONESTOP
+ sb t1, UART0CONFIG(t0) # 8 Bits/1 Stop
+ li t1, TXEN|RXEN|BRGEN
+ sb t1, UART0CONTROL(t0) # Enable, No Parity
+ move t1, zero
+ sh t1, UART0INTMASK(t0)
+
+ .set reorder
+3:
+ j ra
+END(board_earlyinit)
+
+/* *********************************************************************
+ * BOARD_DRAMINFO
+ *
+ * Return the address of the DRAM information table
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * v0 - DRAM info table, return 0 to use default table
+ ********************************************************************* */
+LEAF(board_draminfo)
+ j ra
+END(board_draminfo)
+
+/* *********************************************************************
+ * BOARD_DRAMINIT
+ *
+ * This routine should activate memory.
+ *
+ * Input parameters:
+ * None
+ *
+ * Return value:
+ * None
+ *
+ * Registers used:
+ * can use all registers.
+ ********************************************************************* */
+LEAF(board_draminit)
+ .set noreorder
+
+ move s0,ra
+
+/***** Load DDR Base *************************************/
+ li t0, DDR_BASE
+
+/***** Disable Auto refresh ******************************/
+ li t1, 0x10000
+ sw t1, DDR_CTL_CLKS(t0)
+ SETLEDS1('-','-','-', '-')
+ SETLEDS1('P','H','Y','S')
+
+ li t1, 0x10 // Loop count value
+ li t3, 1
+
+zq_loop:
+ sub t1, t3 // Decrement count by 1
+ beq t1, zero, zq_error
+ nop
+
+ sw zero, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Reset the calibration engine
+ li t4, (1 << 26)
+ sw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Start the calibration
+
+ li t2, 0x100 // Timeout value
+
+wait_zq1:
+ beq t2, zero, zq_timeout
+ nop
+
+ lw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Read the calibration result
+ move t5, t4 // Save calibration result1
+ and t4, (1 << 28)
+ beq t4, zero, wait_zq1
+ sub t2, t3
+
+ sw zero, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Reset the calibration engine
+ li t4, (1 << 26)
+ sw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Start the calibration
+
+ li t2, 0x100 // Timeout value
+
+wait_zq2:
+ beq t2, zero, zq_timeout
+ nop
+
+ lw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Read the calibration result
+ move t6, t4 // Save calibration result1
+ and t4, (1 << 28)
+ beq t4, zero, wait_zq2
+ sub t2, t3
+
+ sw zero, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Reset the calibration engine
+ li t4, (1 << 26)
+ sw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Start the calibration
+
+ li t2, 0x100 // Timeout value
+
+wait_zq3:
+ beq t2, zero, zq_timeout
+ nop
+
+ lw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Read the calibration result
+ move t7, t4 // Save calibration result1
+ and t4, (1 << 28)
+ beq t4, zero, wait_zq3
+ sub t2, t3
+
+ bne t5, t6, zq_loop
+ nop
+ bne t5, t7, zq_loop
+ nop
+ bne t6, t7, zq_loop
+ nop
+
+ b zq_done;
+ nop
+
+zq_error:
+ SETLEDS1('Z','Q','E','R')
+ b zq_done
+ nop
+
+zq_timeout:
+ SETLEDS1('Z','Q','T','O')
+ nop
+zq_done:
+ sw zero, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Reset the calibration engine
+
+ SETLEDS1('Z','Q','D','N')
+ nop
+
+/****** Set control pad strength to half ********/
+ lw t2, PHY_CONTROL_REGS_DRIVE_PAD_CTL(t0)
+ or t2, 0x4
+ sw t2, PHY_CONTROL_REGS_DRIVE_PAD_CTL(t0)
+
+#if defined(_BCM96816_)
+/****** Disable byte lanes 2 and 3 ********/
+ li t1, 0x800fffff
+ sw t1, PHY_BYTE_LANE_2_IDLE_PAD_CONTROL(t0)
+ sw t1, PHY_BYTE_LANE_3_IDLE_PAD_CONTROL(t0)
+#endif
+
+/****** Disable byte lane 1 clock ********/
+ li t1, 1
+ sw t1, PHY_BYTE_LANE_1_CLOCK_PAD_DISABLE(t0)
+
+ddr_x8:
+
+/****** Change the slew and receiver power to full strength in the byte lanes ********/
+ li t1, 0xFFFFFFFC
+ lw t2, PHY_BYTE_LANE_0_DRIVE_PAD_CTL(t0)
+ and t2, t2, t1
+ sw t2, PHY_BYTE_LANE_0_DRIVE_PAD_CTL(t0)
+ lw t2, PHY_BYTE_LANE_1_DRIVE_PAD_CTL(t0)
+ and t2, t2, t1
+ sw t2, PHY_BYTE_LANE_1_DRIVE_PAD_CTL(t0)
+
+/****** Hardware calibrate VDL *******/
+ li t1, 3
+ sw t1, PHY_BYTE_LANE_0_VDL_CALIBRATE(t0)
+ sw t1, PHY_BYTE_LANE_1_VDL_CALIBRATE(t0)
+
+ li t1, 0x1000
+1:
+ bnez t1, 1b
+ addi t1, -1
+
+/****** Check strap value to figure out 400MHz or 200Mhz DDR ******/
+ li t2, MISC_BASE
+ lw t1, MISC_STRAP_BUS(t2)
+
+ srl t1, MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT
+ andi t1, 0x1f // Mask out strap bits
+
+ LOADREL(t2, dram_speed_table)
+
+ add t2, t1
+ lb t1, 0x00(t2)
+ beq t1, zero, ddr_clk_200
+ li t2, 1
+ beq t1, t2, ddr_clk_300
+ nop
+
+/****** Software override rd_en VDL and ADDRESS VDL ********/
+ddr_clk_450:
+ddr_clk_400:
+ li a1, 2 // Set speed to 400MHz (2)
+ b 1f
+ nop
+ddr_clk_300:
+ li a1, 1 // Set speed to 300MHz (1)
+
+/* At higher frequencies set Read_en VDL value to calibrated VDL value + 10 */
+1: li t2, 0x10000
+ lw t1, PHY_BYTE_LANE_0_VDL_STATUS(t0)
+ srl t1, 8
+ addi t1, 0xA
+ or t1, t1, t2
+ sw t1, PHY_BYTE_LANE_0_VDL_OVERRIDE_2(t0)
+ lw t1, PHY_BYTE_LANE_1_VDL_STATUS(t0)
+ srl t1, 8
+ addi t1, 0xA
+ or t1, t1, t2
+ sw t1, PHY_BYTE_LANE_1_VDL_OVERRIDE_2(t0)
+ b vdl_override_cont
+ nop
+
+ddr_clk_200:
+ li a1, 0 // Set speed to 200MHz (0)
+ li t3, 0x1f // Set maximum VDL step size for 200MHz
+ b 1f
+ nop
+
+vdl_override_cont:
+ lw t2, PHY_BYTE_LANE_0_VDL_STATUS(t0)
+ andi t3, t2, 0x1f00
+ srl t3, 8
+ addi t3, t3, 0x4 // Add Stepsize 4
+
+1: li t1, 0x110000 // Enable & Force Override
+ or t1, t3 // Fine rise and fine fall are set to 0
+
+ sw t1, PHY_CONTROL_REGS_STATIC_VDL_OVERRIDE(t0)
+ li t1, 0x0c
+ sw t1, DDR_CTL_DCMD(t0) // Set VDL
+
+ SETLEDS1('P','H','Y','E')
+
+/* Program MC Timing Registers
+
+ Read each timing parameter based on the speed and then create the
+ timing registers and program them.
+*/
+ LOADREL(t2, dram_timing_table)
+
+ li t1, 0x10 // size of dram_timing_table element
+ mult t1, a1
+ mflo t1 // dram_timing_table offset
+ add t2, t1
+
+ move t3, zero
+ lb t1, 0x00(t2) // tRCD
+ andi t1, 0xf
+ move t3, t1
+ lb t1, 0x01(t2) // tCL
+ andi t1, 0xf
+
+ move t4, t1
+ and t4, 0x7 // Make sure that only 3 bits are written to DRAM's tCL field
+ sll t4, 20
+ sw t4, DDR_CTL_DMODE_0 (t0) // Write tCL to the MRS register holder
+
+ sll t1, 4
+ or t3, t1
+ lb t1, 0x02(t2) // tWR
+ andi t1, 0xf
+
+ // Here we create the MRS register values
+ move t4, t1
+ li t5, 1
+ subu t4, t5 // tWR written to DRAM is 1 less than real tWR value
+ andi t4, 0x7
+ sll t4, 25
+ li t5, 0x01030000 // Sequential burst mode, burst of 8, reset DLL
+ or t4, t5
+ lw t5, DDR_CTL_DMODE_0 (t0)
+ or t5, t4
+ sw t5, DDR_CTL_DMODE_0 (t0) // Add tWR to the MRS register holder
+
+ sll t1, 9
+ or t3, t1
+ lb t1, 0x03(t2) // tWL
+ andi t1, 0xf
+ sll t1, 12
+ or t3, t1
+ lb t1, 0x04(t2) // tRP
+ andi t1, 0xf
+ sll t1, 16
+ or t3, t1
+ lb t1, 0x05(t2) // tRRD
+ andi t1, 0xf
+ sll t1, 20
+ or t3, t1
+ lb t1, 0x06(t2) // tRC
+ andi t1, 0x1f
+ sll t1, 24 // tRCw
+ or t3, t1
+ sw t3, DDR_CTL_TIM1_0(t0) // Program TIM1_0 register
+
+ move t3, zero
+ lb t1, 0x06(t2) // tRC
+ andi t1, 0x1f
+ or t3, t1 // tRCr
+ lb t1, 0x07(t2) // tFAW
+ andi t1, 0x3f
+ sll t1, 8
+ or t3, t1
+ li t1, 0xff // tRFC = 0xff (Set to max value first.
+ sll t1, 16 // We'll fix it after we determine dram size)
+ or t3, t1
+
+ // We skip tFIFO since it needs to be 0
+
+ lb t1, 0x08(t2) // tW2R
+ andi t1, 0x3
+ sll t1, 26
+ or t3, t1
+ lb t1, 0x09(t2) // tR2W
+ andi t1, 0x3
+ sll t1, 28
+ or t3, t1
+ lb t1, 0x0a(t2) // tR2R
+ andi t1, 0x1
+ sll t1, 30
+ or t3, t1
+ sw t3, DDR_CTL_TIM1_1(t0) // Program TIM1_1 register
+
+ move t3, zero
+ lb t1, 0x0b(t2) // tAL
+ andi t1, 0xf
+
+ // Here we create the EMRS register values
+ move t4, t1
+ andi t4, 0x7
+ sll t4, 3
+ li t5, 0x384 // RTT=75ohm, OCD Enter
+ or t4, t5
+ lw t5, DDR_CTL_DMODE_0 (t0)
+ or t5, t4
+ sw t5, DDR_CTL_DMODE_0 (t0) // Store required values in EMRS holding register
+
+ or t3, t1
+ lb t1, 0x0c(t2) // tRTP
+ andi t1, 0x7
+ sll t1, 4
+ or t3, t1
+ lb t1, 0x0d(t2) // tW2W
+ andi t1, 0x3
+ sll t1, 8
+ or t3, t1
+ sw t3, DDR_CTL_TIM2(t0) // Program TIM2 register
+
+/*
+// (tRRD is incremented by 1 due to tFAW bug for >=1Gb devices)
+ li t1, 0x18564c55 // tRCD=5,tWR=6,tCL=5,tWL=4,tRP=6,tRRD=5,tRCw=0x18
+// li t1, 0x13554a55 // tRCD=5,tWR=5,tCL=5,tWL=4,tRP=5,tRRD=5,tRCw=0x13
+ sw t1, DDR_CTL_TIM1_0(t0)
+ li t1, 0x18330018 // tR2W=1,tR2R=0,tW2R=2,tFIFO=0,tRFC=0x33,tFAW=0,tRCr=0x18
+// li t1, 0x182b0013 // tR2W=1,tR2R=0,tW2R=2,tFIFO=0,tRFC=0x2b,tFAW=0,tRCr=0x13
+ sw t1, DDR_CTL_TIM1_1(t0)
+ li t1, 0x00000034 // tAL=4 (tRCD-1), tRTP=3, tW2W=0
+ sw t1, DDR_CTL_TIM2(t0)
+*/
+
+// Set x16 mode and Page policy
+ li t1, 0x100
+ sw t1, DDR_CTL_DMODE_1(t0)
+
+// Enable ODT for writes
+ li t1, 0x104
+ sw t1, DDR_CTL_ODT(t0)
+
+/***** Turn on CKE ***************/
+ li t1, 0x35
+ sw t1, DDR_CTL_DCMD(t0)
+
+ li t1, 0x200
+2:
+ bnez t1, 2b
+ addi t1, -1
+
+/***** Set arbitor for Burst Round Robin Mode ***/
+ lw t1, DDR_CTL_ARB(t0)
+ or t1, 4 << 16
+ sw t1, DDR_CTL_ARB(t0)
+
+/***** Issue Precharge All Banks Command ***/
+ li t1, 0x32
+ sw t1, DDR_CTL_DCMD(t0)
+
+/***** Issue EMRS2 Command ***/
+ li t1, 0x0
+ lw t2, DDR_CTL_DMODE_0 (t0) // Load previous value to t2 to preserve it
+ nop
+ sw t1, DDR_CTL_DMODE_0 (t0)
+ li t1, 0x38
+ sw t1, DDR_CTL_DCMD(t0)
+
+/***** Issue EMRS3 Command***/
+ li t1, 0x0
+ sw t1, DDR_CTL_DMODE_0 (t0)
+ li t1, 0x39
+ sw t1, DDR_CTL_DCMD(t0)
+
+// Enable DLL by issuing EMRS Command
+// li t1, 0x0
+// sw t1, DDR_CTL_DMODE_0 (t0)
+ sw t2, DDR_CTL_DMODE_0 (t0) // Use the saved value back to DMODE_0 register
+ li t1, 0x30
+ sw t1, DDR_CTL_DCMD(t0)
+
+/*
+// Issue MRS Command tCL=5 tWL=4
+ li t1, 0x0b530000
+// li t1, 0x07530000 // tCL=5 tWR=5, Reset DLL, Sequential Mode, Burst Length = 8
+ sw t1, DDR_CTL_DMODE_0 (t0)
+ li t1, 0x31
+ sw t1, DDR_CTL_DCMD(t0)
+*/
+// Issue MRS Command. Set Reset DLL bit
+ li t1, 0x31
+ sw t1, DDR_CTL_DCMD(t0)
+
+// Issue Precharge All Banks Command
+ li t1, 0x32
+ sw t1, DDR_CTL_DCMD(t0)
+
+// Issue Autorefresh Command
+ li t1, 0x33
+ sw t1, DDR_CTL_DCMD(t0)
+ li t1, 0x33
+ sw t1, DDR_CTL_DCMD(t0)
+
+ li t1, 0x200
+3:
+ bnez t1, 3b
+ addi t1, -1
+
+/*
+// Clear DLL Reset by Issuing MRS Command, tCL=5 tWL=4
+ li t1, 0x0a530000
+ sw t1, DDR_CTL_DMODE_0 (t0)
+ li t1, 0x31
+ sw t1, DDR_CTL_DCMD(t0)
+*/
+
+// Issue MRS Command w/ DLL Reset bit set to 0
+ lw t1, DDR_CTL_DMODE_0 (t0)
+ li t2, 0xFEFFFFFF // Reset DLL reset bit
+ and t1, t2
+ sw t1, DDR_CTL_DMODE_0 (t0)
+ li t1, 0x31
+ sw t1, DDR_CTL_DCMD(t0)
+
+/*
+// Issue EMRS Command (Enter OCD Calibration)
+ li t1, 0x380
+ sw t1, DDR_CTL_DMODE_0 (t0)
+ li t1, 0x30
+ sw t1, DDR_CTL_DCMD(t0)
+*/
+
+// Issue EMRS Command (Enter OCD Calibration) 75 Ohm, Full strength Drive, tAL=tRCD-1
+ li t1, 0x30
+ sw t1, DDR_CTL_DCMD(t0)
+
+// Issue EMRS Command (Exit OCD Calibration)
+ lw t1, DDR_CTL_DMODE_0 (t0)
+ li t2, 0xFC7F // Reset OCD field for exit mode
+ and t1, t2
+ sw t1, DDR_CTL_DMODE_0 (t0)
+ li t1, 0x30
+ sw t1, DDR_CTL_DCMD(t0)
+
+// Check x8 or x16 DDR
+ li t1, 0x12345678
+ li t3, 0xA0000000
+ sw zero, 0(t3)
+ sw t1, 0(t3)
+ lw t2, 0(t3)
+ bne t1, t2, 3f // Failed
+ nop
+// Do the test twice. Just in case random values match...
+ li t1, 0x87654321
+ sw t1, 0(t3)
+ lw t2, 0(t3)
+ beq t1, t2, 1f // Clock lines are enabled as needed
+ nop
+
+3:
+// Memory test failed. Need to re-enable byte lane 1 clock
+ sw zero, PHY_BYTE_LANE_1_CLOCK_PAD_DISABLE(t0)
+ li t1, 0x200
+2:
+ bnez t1, 2b // Delay after enabling clocks
+ addi t1, -1
+ b ddr_x8
+ nop
+
+1:
+// Find memory size. a3 keeps the size: 0=256Mb, 1=512Mb, 2=1Gb, 3=2Gb
+// Start from 2Gb device
+ LOADREL(t7, dram_map_table_x8)
+ lw t1, PHY_BYTE_LANE_1_CLOCK_PAD_DISABLE(t0)
+ beqz t1, 1f
+ nop
+ LOADREL(t7, dram_map_table_x16)
+
+1:
+ li a3, 4
+ddr_size:
+ addi a3, -1
+
+ li t1, 0x2c // size of dram_map_table element
+ mult t1, a3
+ mflo t2 // dram_map_table offset
+ add t2, t7
+
+ lw t1, 0x00(t2) // Row00_0
+ sw t1, DDR_CTL_ROW00_0(t0)
+
+ lw t1, 0x04(t2) // Row00_1
+ sw t1, DDR_CTL_ROW00_1(t0)
+
+ lw t1, 0x08(t2) // Row01_0
+ sw t1, DDR_CTL_ROW01_0(t0)
+
+ lw t1, 0x0C(t2) // Row01_1
+ sw t1, DDR_CTL_ROW01_1(t0)
+
+ lw t1, 0x10(t2) // Col00_0
+ sw t1, DDR_CTL_COL00_0(t0)
+
+ lw t1, 0x14(t2) // Col00_1
+ sw t1, DDR_CTL_COL00_1(t0)
+
+ lw t1, 0x18(t2) // Col01_0
+ sw t1, DDR_CTL_COL01_0(t0)
+
+ lw t1, 0x1C(t2) // Col01_1
+ sw t1, DDR_CTL_COL01_1(t0)
+
+ lw t1, 0x20(t2) // Bank
+ sw t1, DDR_CTL_BNK10(t0)
+
+ li t1, 0x0 // CS_Start
+ sw t1, DDR_CTL_CSST(t0)
+
+ lw t1, 0x24(t2) // CS_End
+ sw t1, DDR_CTL_CSEND(t0)
+
+ li t1, 0x0 // CS Interleaving CFG
+ sw t1, DDR_CTL_CNFG(t0)
+
+ lw t3, 0x28(t2) // Dram Size
+ lw t1, DDR_CTL_GCFG(t0) // GCFG
+ li t2, 0xFFFFFF00
+ and t1, t1, t2 // Mask out Dram Size Fields
+ or t1, t3, t1 // insert new DRAM Size value
+ sw t1, DDR_CTL_GCFG(t0)
+ beqz a3, ddr_speed
+ nop
+
+// Check for memory aliasing
+// This assumes that the bank interleaving is below address bits 8.
+ li t1, 8
+ li t2, 24
+ add t2, a3 // Scan up to maximum memory size
+ li t3, 0xA0000000
+
+check_alias:
+ li t4, 1
+ sll t4, t1
+ add t4, t3
+
+ sw zero, 0(t3)
+ li t5, -1
+ sw t5, 0(t4)
+ lw t6, 0(t3)
+
+ beq t5, t6, ddr_size
+ nop
+
+ bne t1, t2, check_alias
+ addi t1, 1
+
+ddr_speed:
+ li t1, 3
+ lw t2, PHY_BYTE_LANE_1_CLOCK_PAD_DISABLE(t0)
+ beqz t2, 1f
+ nop
+ li t1, 2
+1:
+ blt a3, t1, tRefi_update // If smaller than 1Gb device, keep tRRD same
+ nop
+
+ lw t1, DDR_CTL_TIM1_0(t0) // Load DDR_CTL_TIM1_0 register
+ move t2, t1
+ srl t2, 20
+ andi t2, 0xf
+ addi t2, 1 // Increment ttRRD by one (software work around for a bug)
+ sll t2, 20
+ li t3, 0xFF0FFFFF
+ and t1, t3 // Clear tRRD field
+ or t1, t2 // Insert the new tRRD value
+ sw t1, DDR_CTL_TIM1_0(t0) // Store DDR_CTL_TIM1_0 register
+ nop
+
+tRefi_update:
+ LOADREL(t2, dram_tRefi_table)
+
+ li t1, 0x4 // size of dram_tRefi_table entry
+ mult t1, a1
+ mflo t1 // dram_tRefi_table offset
+ add t2, t1
+
+ lw t1, 0x0(t2) // tRefi
+ sll t1, 8
+ sw t1, DDR_CTL_CLKS(t0)
+
+ LOADREL(t2, dram_tRFC_table)
+
+ li t1, 0x4 // size of dram_tRFC_table entry
+ mult t1, a1
+ mflo t1 // dram_tRefi_table offset
+ add t2, t1 // Calculate address in the row
+
+ li t1, 0xc // size of dram_tRFC_table row
+ mult t1, a3
+ mflo t1 // dram_tRefi_table offset
+ add t2, t1 // Calculate address in the column
+
+ lw t3, 0x0(t2) // Load tRFC value
+ andi t3, 0xFF // Mask tRFC to 8-bits
+ sll t3, 16 // Move it to bit location [23:16]
+
+ lw t1, DDR_CTL_TIM1_1(t0) // Load DDR_CTL_TIM1_1 register
+ li t2, 0xFF00FFFF
+ and t1, t1, t2 // Mask out tRFC Field
+ or t1, t3, t1 // insert new tRFC value
+ sw t1, DDR_CTL_TIM1_1(t0) // Write to TIM1_1 register
+
+ SETLEDS1('D','I','N','T')
+
+/***** UBUS align to MEMC *****/
+align_memc:
+
+/*** check MEMC clk ratio to set sampling freq *****/
+ li t2, MISC_BASE
+ lw t1, MISC_STRAP_BUS(t2)
+
+ srl t1, MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT
+ andi t1, 0x1f // Mask out strap bits
+
+#if defined(_BCM96816_)
+ LOADREL(t2, periph_fix_table)
+ lw t2, 0(t2)
+ srl t2, t1
+ andi t2, 1
+ bne t2, zero, 2f
+#endif
+
+ LOADREL(t2, memc_ubus_ratio_table)
+
+ add t2, t1
+ lb t1, 0x00(t2)
+ sll t4,t1,28 // Update Sampling Period Field
+
+pi_ubus:
+ li t2, 4048
+ li t3, 1
+
+ sw zero, DDR_CTL_PI_GCF(t0)
+ li t1, 0x00001c0b // send feedback command every 11 cycles
+ or t1, t1, t4
+ sw t1, DDR_CTL_PI_UBUS_SMPL(t0)
+ ori t1, 0x80 // trigger stoke signal to latch in new counter value
+ sw t1, DDR_CTL_PI_UBUS_SMPL(t0)
+ li t1, 0x00040000 // send new phase value to PLL every 5 cycles
+ sw t1, DDR_CTL_PI_UBUS_CTL(t0)
+ li t1, 0x00000001 // enable enable counter that change PLL phase
+ sw t1, DDR_CTL_PI_GCF(t0)
+ nop
+
+#if defined (_BCM96328_) || defined(_BCM96362_)
+// Enable PHY MIPS PI
+ li t1, 0x00130000
+ sw t1, DDR_CTL_PI_DSL_MIPS_CTL(t0)
+ nop
+#endif
+
+1:
+ lw t4, DDR_CTL_PI_UBUS_SMPL(t0) // Read a sample value.
+ srl t4, 16 // The sample is in the upper 16 bits.
+
+ andi t4, t4, 0x22 // Look at the 2 outermost bits; if the LSB is 0 and the MSB is 1,
+ beq t4, 0x20, 2f // then there is an edge somewhere in the sample.
+ nop
+ lw t5, DDR_CTL_PI_UBUS_CTL(t0)
+ and t5, 0xffff0000
+ or t5, t3
+ or t5, (1<<14) // move phase in positive direction
+ sw t5, DDR_CTL_PI_UBUS_CTL(t0)
+ nop
+ lw t5, DDR_CTL_PI_UBUS_CTL(t0) // Delay before reading another sample.
+ add t3, 1
+ bne t2, t3, 1b
+ nop
+
+ SETLEDS1('U','A','S','Y')
+ SETLEDS1('L','A','S','Y')
+ SETLEDS1('M','A','S','Y')
+ b run_async // failed to set sync mode
+ nop
+
+2:
+/*** check MIPS clk ratio *****/
+ li t4, 0xff410010
+ li t2, MISC_BASE
+ lw t1, MISC_STRAP_BUS(t2)
+
+ srl t1, MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT
+ andi t1, 0x1f // Mask out strap bits
+
+ b _mips_align_2_ubus // none of the above means it is either 1/1 or 2/1
+ nop
+
+
+_mips_align_2_ubus:
+
+/***** MIPS align to UBUS *****/
+ li t1, 0xff410000
+
+ li t2, 0x00040000 // update PLL phase value every 5 MC cycles
+ sw t2, DDR_CTL_PI_MIPS_CTL(t0)
+
+ li t2, 0xc0001c03 // force update on mclk_period
+ sw t2, 0x40(t1)
+ li t2, 0x80001c83
+ sw t2, 0x40(t1)
+
+ lw t2, DDR_CTL_PI_MIPS_CTL(t0) // add delay
+ li t3, 1
+
+1: lw t4, 0x40(t1) // Read a sample value.
+ srl t4, 16 // The sample is in the upper 16 bits.
+
+ andi t4, t4, 0x22 // Look at the 2 outermost bits, if the LSB is 0 and the MSB is 1,
+ beq t4, 0x20, 2f // then there is an edge somewhere in the sample.
+ nop
+ lw t5, DDR_CTL_PI_MIPS_CTL(t0)
+ and t5, 0xffff0000
+ or t5, t3
+ or t5, (1<<14) // move phase in positive direction
+ sw t5, DDR_CTL_PI_MIPS_CTL(t0)
+ nop
+ lw t5, DDR_CTL_PI_MIPS_CTL(t0) // Delay before reading another sample.
+ add t3, 1
+ bne t2, t3, 1b
+ nop
+
+ SETLEDS1('U','A','S','Y')
+ SETLEDS1('L','A','S','Y')
+ SETLEDS1('M','A','S','Y')
+ b run_async // failed to set sync mode
+ nop
+2:
+ // Success
+ lw t2, DDR_CTL_PI_MIPS_CTL(t0) // Turn on auto-PI mode.
+ or t2, (1 << 20) // PI_UBUS_CTL_Hw_Cntr_En = 1
+ sw t2, DDR_CTL_PI_MIPS_CTL(t0)
+
+ /**----- Enable DDR/UBUS and DDR/LMB sync mode ------------------**/
+ /*** only MIPS in sync mode for these strap options */
+
+ li t2, MISC_BASE
+ lw t1, MISC_STRAP_BUS(t2)
+
+ srl t1, MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT
+ andi t1, 0x1f // Mask out strap bits
+
+ li t3, 0 // Used to keep MC/MIPS and MC/UBUS sync/async mode
+
+ LOADREL(t2, dram_sync_table)
+
+ lw t4, 0x0(t2) // Ubus Sync vector
+ lw t5, 0x4(t2) // Lmb Sync vector
+
+#if defined (_96816_)
+ move t4, t6
+#endif
+ lw t6, 0x8(t2) // Mips Sync vector
+
+ srl t4, t1 // Get the ubus sync flag
+ srl t5, t1 // Get the lmb sync flag
+ srl t6, t1 // Get the mips sync flag
+ andi t4, 1 // Mask out other bits
+ andi t5, 1 // Mask out other bits
+ andi t6, 1 // Mask out other bits
+
+ li t2, 1
+ bne t4, t2, ubus_async // 1f below. If ubus is not sync, lmb can't be in sync
+ nop // Go to ubus_async (1f)
+
+ // Ubus Sync Mode. Turn on Ubus Clock tracking
+ lw t2, DDR_CTL_PI_UBUS_CTL(t0) // Turn on auto-PI mode.
+ or t2, (1 << 20) // PI_UBUS_CTL_Hw_Cntr_En = 1
+ sw t2, DDR_CTL_PI_UBUS_CTL(t0)
+
+ // Is LMB Sync as well?
+ li t2, 1
+ beq t5, t2, memc_all_sync // If both ubus and lmb are sync, go to memc_all_sync
+ nop
+
+memc_ubus_sync:
+#if UBUS_SYNC_ENABLE
+// set MC/UBUS to SYNC
+ li t3, 0x4
+ SETLEDS1('L','A','S','Y')
+ SETLEDS1('U','S','Y','N')
+#else
+// set MC/UBUS to ASYNC
+ li t3, 0xc
+ SETLEDS1('L','A','S','Y')
+ SETLEDS1('U','A','S','Y')
+#endif
+
+ b update_sync_mode
+ nop
+
+memc_all_sync:
+#if LMB_SYNC_ENABLE
+// set MC/MIPS to SYNC
+ nop
+ SETLEDS1('L','S','Y','N')
+#else
+// set MC/MIPS to ASYNC
+ li t1, 0x4
+ or t3, t1
+ SETLEDS1('L','A','S','Y')
+#endif
+#if UBUS_SYNC_ENABLE
+// set MC/UBUS to SYNC
+ nop
+ SETLEDS1('U','S','Y','N')
+#else
+// set MC/UBUS to ASYNC
+ li t1, 0x8
+ or t3, t1
+ SETLEDS1('U','A','S','Y')
+#endif
+
+update_sync_mode:
+ li t1, MISC_BASE
+ sw t3, MISC_MEMC_CONTROL(t1)
+ b 2f
+ nop
+1:
+ubus_async:
+ SETLEDS1('L','A','S','Y')
+ SETLEDS1('U','A','S','Y')
+
+2:
+ // Can Mips run in sync mode? If not, skip all below
+ beq t6, zero, run_async
+ nop
+
+#if MIPS_SYNC_ENABLE
+ /**----- Clear MIPS Async mode bit ------------------------------**/
+ mfc0 t1, C0_BCM_CONFIG, 5
+ and t1, ~(0x1 << 28)
+ mtc0 t1, C0_BCM_CONFIG, 5
+
+ SETLEDS1('M','S','Y','N')
+#else
+ SETLEDS1('M','A','S','Y')
+#endif
+
+3:
+ /**----- Enable RAC and LMB -------------------------------------**/
+ li t0, MIPS_BASE
+ lw t2, MIPS_LMB_CR(t0)
+#if LMB_ENABLE
+ or t2, LMB_EN // Enable LMB
+ SETLEDS1('L','M','B','E')
+#else
+ SETLEDS1('L','M','B','D')
+#endif
+ sw t2, MIPS_LMB_CR(t0)
+
+ li t2, 0xFFF << RAC_UPB_SHFT // Enable prefetch for RAM address range up to 256MB
+ sw t2, MIPS_RAC_ARR(t0)
+
+ lw t2, MIPS_RAC_CR0(t0)
+ or t2, (RAC_C_INV | RAC_I | RAC_PF_I)
+ sw t2, MIPS_RAC_CR0(t0)
+
+ lw t2, MIPS_RAC_CR1(t0)
+ or t2, (RAC_C_INV | RAC_I | RAC_PF_I)
+ sw t2, MIPS_RAC_CR1(t0)
+
+run_async:
+ /**----- Enable branch prediction and non-blocking data cache ---**/
+ mfc0 t1, C0_BCM_CONFIG
+ and t1, ~CP0_BCM_CFG_BTHD
+ or t1, CP0_BCM_CFG_NBK
+ or t1, CP0_BCM_CFG_CLF
+ mtc0 t1, C0_BCM_CONFIG
+
+#if DDR_TEST
+#######################################
+# Run test on DRAM using Test Engine #
+#######################################
+#define BACKGND_MODE_DATA 0x0
+#define BACKGND_MODE_LFSR 0x400
+#define BACKGND_MODE_PRBS 0x800
+#define BACKGND_MODE_NOT_PRBS 0xc00
+#define BACKGND_MODE_PAT 0x1000
+#define BACKGND_MODE_NOT_PAT 0x1400
+
+#define VICT_MODE_PRBS 0
+#define VICT_MODE_NOT_PRBS 0x100
+#define VICT_MODE_PAT 0x200
+#define VICT_MODE_NOT_PAT 0x300
+
+#define VICT_ENABLE 0x8000
+#define VICT_SWEEP_ENABLE 0x10000
+#define VICT_COUNT 0x0
+
+#define PRBS_ORDER(x) ((x & 0x3) << 13)
+
+#define TEST_COUNT 0x1000
+#define TEST_ADDR 0x0
+#define TEST_ADDR_UPDT 0x1
+#define TEST_PATTERN0 0x5555
+#define TEST_PATTERN1 0xaaaa
+#define TEST_PATTERN (TEST_PATTERN1 << 16 | TEST_PATTERN0)
+
+#define TEST_ENABLE 0x1
+#define TEST_DONE 0x2
+#define TEST_ERROR 0x4
+#define TEST_WRITE 0x10
+#define TEST_READ 0x0
+
+#define BACKGND_DATA0 0xa5a5a5a5
+#define BACKGND_DATA1 0x5a5a5a5a
+#define BACKGND_DATA2 0xa5a5a5a5
+#define BACKGND_DATA3 0x5a5a5a5a
+
+#define TEST_DATA0 0x02468ace
+#define TEST_DATA1 0x13579bdf
+#define TEST_DATA2 0x33cccc33
+#define TEST_DATA3 0x55aaaa55
+
+/***** Load DDR Base *************************************/
+ li t0, DDR_BASE
+ li t1, BACKGND_DATA0
+ sw t1, DDR_CTL_TEST_DATA0(t0)
+ li t1, BACKGND_DATA1
+ sw t1, DDR_CTL_TEST_DATA1(t0)
+ li t1, BACKGND_DATA2
+ sw t1, DDR_CTL_TEST_DATA2(t0)
+ li t1, BACKGND_DATA3
+ sw t1, DDR_CTL_TEST_DATA3(t0)
+ li t1, TEST_COUNT
+ li t2, VICT_COUNT
+ or t1, t2 # add victim count value
+ sw t1, DDR_CTL_TEST_COUNT(t0)
+ li t1, TEST_ADDR
+ sw t1, DDR_CTL_TEST_ADDR(t0)
+ li t1, TEST_ADDR_UPDT
+ sw t1, DDR_CTL_TEST_ADDR_UPDT(t0)
+ li t1, TEST_PATTERN
+ sw t1, DDR_CTL_TEST_PAT(t0)
+
+# Write a background pattern first
+ li t1, BACKGND_MODE_DATA
+ li t2, TEST_WRITE
+ or t1, t2
+ li t2, TEST_ENABLE
+ or t1, t2
+ sw t1, DDR_CTL_TEST_CFG1(t0)
+
+ li t2, 0x2
+ li t3, MISC_BASE
+
+ li t5, 0x10000
+2: li t1, 0x100
+1: addiu t1, -1
+ bnez t1, 1b
+ nop
+
+ lw t4, MISC_MEMC_CONTROL(t3)
+ and t4, 0x2
+ beq t4, t2, backgnd_write_done
+ nop
+ addiu t5, -1
+ bnez t5, 2b
+ nop
+
+# Background write operation is finished
+
+backgnd_write_done:
+ li t1, TEST_DATA0
+ sw t1, DDR_CTL_TEST_DATA0(t0)
+ li t1, TEST_DATA1
+ sw t1, DDR_CTL_TEST_DATA1(t0)
+ li t1, TEST_DATA2
+ sw t1, DDR_CTL_TEST_DATA2(t0)
+ li t1, TEST_DATA3
+ sw t1, DDR_CTL_TEST_DATA3(t0)
+ li t1, TEST_COUNT
+ li t2, VICT_COUNT
+ or t1, t2 # add victim count value
+ sw t1, DDR_CTL_TEST_COUNT(t0)
+ li t1, TEST_ADDR
+ sw t1, DDR_CTL_TEST_ADDR(t0)
+ li t1, TEST_ADDR_UPDT
+ sw t1, DDR_CTL_TEST_ADDR_UPDT(t0)
+ li t1, TEST_PATTERN
+ sw t1, DDR_CTL_TEST_PAT(t0)
+
+# li t1, BACKGND_MODE_DATA
+# li t1, BACKGND_MODE_PAT
+# li t2, VICT_MODE_NOT_PAT
+ li t1, BACKGND_MODE_PRBS
+ li t2, VICT_MODE_NOT_PRBS
+
+ or t1, t2
+ li t2, VICT_ENABLE
+ or t1, t2
+ li t2, VICT_SWEEP_ENABLE
+ or t1, t2
+ li t2, PRBS_ORDER(0)
+ or t1, t2
+ li t2, TEST_WRITE
+ or t1, t2
+ li t2, TEST_ENABLE
+ or t1, t2
+ sw t1, DDR_CTL_TEST_CFG1(t0)
+
+ li t2, 0x2
+ li t3, MISC_BASE
+
+ li t5, 0x10000
+2: li t1, 0x100
+1: addiu t1, -1
+ bnez t1, 1b
+ nop
+
+ lw t4, MISC_MEMC_CONTROL(t3)
+ and t4, 0x2
+ beq t4, t2, test_write_done
+ nop
+ addiu t5, -1
+ bnez t5, 2b
+ nop
+
+# Test write operation is finished
+
+test_write_done:
+ li t1, TEST_DATA0
+ sw t1, DDR_CTL_TEST_DATA0(t0)
+ li t1, TEST_DATA1
+ sw t1, DDR_CTL_TEST_DATA1(t0)
+ li t1, TEST_DATA2
+ sw t1, DDR_CTL_TEST_DATA2(t0)
+ li t1, TEST_DATA3
+ sw t1, DDR_CTL_TEST_DATA3(t0)
+ li t1, TEST_COUNT
+ li t2, VICT_COUNT
+ or t1, t2 # add victim count value
+ sw t1, DDR_CTL_TEST_COUNT(t0)
+ li t1, TEST_ADDR
+ sw t1, DDR_CTL_TEST_ADDR(t0)
+ li t1, TEST_ADDR_UPDT
+ sw t1, DDR_CTL_TEST_ADDR_UPDT(t0)
+ li t1, TEST_PATTERN
+ sw t1, DDR_CTL_TEST_PAT(t0)
+
+# li t1, BACKGND_MODE_DATA
+# li t1, BACKGND_MODE_PAT
+# li t2, VICT_MODE_NOT_PAT
+ li t1, BACKGND_MODE_PRBS
+ li t2, VICT_MODE_NOT_PRBS
+
+ or t1, t2
+ li t2, VICT_ENABLE
+ or t1, t2
+ li t2, VICT_SWEEP_ENABLE
+ or t1, t2
+ li t2, PRBS_ORDER(0)
+ or t1, t2
+ li t2, TEST_READ
+ or t1, t2
+ li t2, TEST_ENABLE
+ or t1, t2
+ sw t1, DDR_CTL_TEST_CFG1(t0)
+
+ li t3, MISC_BASE
+ li t2, 0x2
+
+ li t5, 0x10000
+2: li t1, 0x100
+1: addiu t1, -1
+ bnez t1, 1b
+ nop
+
+ lw t4, MISC_MEMC_CONTROL(t3)
+ and t4, 0x2
+ beq t4, t2, test_read_done
+ nop
+ addiu t5, -1
+ bnez t5, 2b
+ nop
+
+# Test read operation is finished
+
+test_read_done:
+ lw t1, DDR_CTL_TEST_CFG1(t0)
+ srl t1, 2
+ and t1, 1
+ beq t1, zero, test_passed
+ nop
+
+test_failed:
+ SETLEDS1('F','A','I','L')
+ b 1f
+ nop
+test_passed:
+ SETLEDS1('P','A','S','S')
+1:
+ SETLEDS1('-','-','-', '-')
+#endif
+
+ move ra,s0
+ j ra
+ nop
+
+ .set reorder
+
+END(board_draminit)
+
+/* *********************************************************************
+ * BOARD_SETLEDS(x)
+ *
+ * Set LEDs for boot-time progress indication. Not used if
+ * the board does not have progress LEDs. This routine
+ * must not call any other routines, since it may be invoked
+ * either from KSEG0 or KSEG1 and it may be invoked
+ * whether or not the icache is operational.
+ *
+ * Input parameters:
+ * a0 - LED value (8 bits per character, 4 characters)
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * t7,t8,t9
+ ********************************************************************* */
+LEAF(board_setleds)
+#if 1
+ li t7, UART_BASE
+ li t8, TXFIFOEMT
+
+1: lh t9, UART0INTSTAT(t7)
+ and t9, t8
+ bne t9, t8, 1b
+
+ srl t8, a0, 24
+ sb t8, UART0DATA(t7)
+ srl t8, a0, 16
+ sb t8, UART0DATA(t7)
+ srl t8, a0, 8
+ sb t8, UART0DATA(t7)
+ sb a0, UART0DATA(t7)
+ li a0, '\r'
+ sb a0, UART0DATA(t7)
+ li a0, '\n'
+ sb a0, UART0DATA(t7)
+#endif
+ j ra
+END(board_setleds)
+
+/* *********************************************************************
+ * BCMCORE_TP1_SWITCH()
+ *
+ * Check if the thread switch is required. If we are already
+ * running on thread 1 this function will do nothing and just return
+ * If we are running on thread 0 this function will take thread 1
+ * out of reset and put thread 0 to sleep waiting for singnal from
+ * thread 1.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+LEAF(bcmcore_tp1_switch)
+
+#if defined(_BCM96328_)
+ li t1, OTP_BASE
+ addi t1, OTP_USER_BITS
+ addi t1, 0xc - ((OTP_TP1_DISABLE_BIT / 8) & ~3)
+ lw t0, 0(t1)
+ andi t0, 1 << (OTP_TP1_DISABLE_BIT % 32)
+ beqz t0, 1f
+ j ra
+1:
+#endif
+ mfc0 t1, C0_BCM_CONFIG, 3
+ li t2, CP0_CMT_TPID
+ and t1, t2
+ bnez t1, tp1 # Already running on thread 1
+
+# Start TP1
+# Set boot address for TP1
+ li t1, MIPS_BASE
+ li t2, 0x98000000 | ENABLE_ALT_BV
+ sw t2, MIPS_TP1_ALT_BV(t1)
+
+# Set a flag so we can wait for TP1 to catch up
+ li t1, 0x0
+ mtc0 t1, $31 # CO_DESAVE
+
+# Take TP1 out of reset
+ mfc0 t1, C0_BCM_CONFIG, 2
+ or t1, CP0_CMT_RSTSE
+ mtc0 t1, C0_BCM_CONFIG, 2
+
+ /* wait until second thread catches up with the first */
+waittp1:
+ mfc0 t0, $31 # CO_DESAVE
+ beqz t0, waittp1
+
+ li t0, THREAD_NUM_ADDRESS
+ FIXUP(t0)
+ lw t0, 0(t0)
+ li t1, 1
+ bne t0, t1, return # Linux will run on TP0, continue running bootloader
+
+# Voice will run on TP0. Set it up and put it to sleep
+
+ # enable interrupts and enable SW IRQ 0
+ li t0, M_SR_IE | M_SR_IBIT1
+ mtc0 t0, C0_SR
+
+ # Set up to use alternate exception vector 0x80000200
+ li t0, M_CAUSE_IV
+ mtc0 t0, C0_CAUSE
+
+ mfc0 t1, C0_BCM_CONFIG, 1
+ # set all ints except IRQ1 to TP1 and cross over SW IRQ 0
+ or t1, (CP0_CMT_XIR_4 | CP0_CMT_XIR_3 | CP0_CMT_XIR_2 | CP0_CMT_XIR_0 | CP0_CMT_SIR_0 | CP0_CMT_NMIR_TP1)
+ mtc0 t1, C0_BCM_CONFIG, 1
+
+ mfc0 t1, C0_BCM_CONFIG, 2
+ # Set debug on TP1, give priority to TP0, and
+ # set TLB exception serialization to ignore SCNT value in CP0 reg22 sel 4
+ and t1, ~CP0_CMT_TPS_MASK;
+ or t1, (CP0_CMT_DSU_TP1 | CP0_CMT_PRIO_TP0 | (1 << CP0_CMT_TPS_SHFT))
+ mtc0 t1, C0_BCM_CONFIG, 2
+
+ # Enable Data RAC on TP0
+ li t1, MIPS_BASE
+ lw t2, MIPS_RAC_CR0(t1)
+ or t2, (RAC_D | RAC_PF_D)
+ sw t2, MIPS_RAC_CR0(t1)
+
+2:
+ b wait_for_wake
+
+tp1:
+# Running on TP1....
+# First signal to TP0 that TP1 is up
+ li t1, 0x1
+ mtc0 t1, $31 # CO_DESAVE
+
+ li t0, THREAD_NUM_ADDRESS
+ FIXUP(t0)
+ lw t0, 0(t0)
+ li t1, 1
+ beq t0, t1, return # Linux will run on TP1, continue running bootloader
+
+# Voice will run on TP1. Set it up and put it to sleep
+
+ # enable interrupts and enable SW IRQ 0
+ li t0, M_SR_IE | M_SR_IBIT1
+ mtc0 t0, C0_SR
+
+ # Set up to use alternate exception vector 0x80000200
+ li t0, M_CAUSE_IV
+ mtc0 t0, C0_CAUSE
+
+ mfc0 t1, C0_BCM_CONFIG, 1
+ # set IRQ1 to TP1 and cross over SW IRQ 0
+ or t1, (CP0_CMT_XIR_1 | CP0_CMT_SIR_0 | CP0_CMT_NMIR_TP0)
+ mtc0 t1, C0_BCM_CONFIG, 1
+
+ mfc0 t1, C0_BCM_CONFIG, 2
+ # Set debug on TP0, give priority to TP1, and
+ # set TLB exception serialization to ignore SCNT value in CP0 reg22 sel 4
+ and t1, ~CP0_CMT_TPS_MASK;
+ or t1, (CP0_CMT_PRIO_TP1 | (1 << CP0_CMT_TPS_SHFT))
+ mtc0 t1, C0_BCM_CONFIG, 2
+
+ # Enable Data RAC on TP1
+ li t1, MIPS_BASE
+ lw t2, MIPS_RAC_CR1(t1)
+ or t2, (RAC_D | RAC_PF_D)
+ sw t2, MIPS_RAC_CR1(t1)
+ b 2b
+
+return:
+ j ra
+
+END(bcmcore_tp1_switch)
+
+# align this code to cache line. NAND flash is not memory mapped after system boots
+# so when we are signaling to the second TP to wake we need
+# jal instruction to be in cache
+ .align 4
+LEAF(wait_for_wake)
+ sync
+ wait # wait for interrupt
+ jal t8 # jump to entry point
+END(wait_for_wake)
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_main.c b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_main.c
new file mode 100755
index 0000000..201d6d8
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_main.c
@@ -0,0 +1,649 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Main Module File: bcm63xxBoot_main.c
+ *
+ * This module contains the main "C" routine for CFE bootstrap loader
+ * and decompressor to decompress the real CFE to ram and jump over.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ * Revised: seanl
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_timer.h"
+
+#include "env_subr.h"
+#include "ui_command.h"
+#include "cfe_mem.h"
+#include "cfe.h"
+
+#include "bsp_config.h"
+#include "bcm_hwdefs.h"
+#include "bcm_map.h"
+
+#include "exception.h"
+
+#include "segtable.h"
+
+#include "initdata.h"
+
+#if defined(_BCM96368_) || defined(_BCM96362_) || defined(_BCM96328_) || defined(_BCM96816_)
+#include "flash_api.h"
+#include "jffs2.h"
+#endif
+
+#if CFG_PCI
+#include "pcivar.h"
+#endif
+
+
+
+int cfe_size_ram(void);
+inline static int is_aliased(int max_bits) __attribute__((always_inline));
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#ifndef CFG_STACK_SIZE
+#define STACK_SIZE 8192
+#else
+#define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023)
+#endif
+
+inline static int is_aliased(int max_bits)
+{
+ volatile uint32 *mem_base;
+ volatile uint32 *test_ptr;
+ uint32 tmp;
+ int bit;
+ int res = 0;
+
+ mem_base = (uint32*)DRAM_BASE_NOCACHE;
+
+ *mem_base = 0;
+
+ for (bit = 8; bit < max_bits; bit++) {
+ test_ptr = (uint32*)((uint32)mem_base | 1 << bit);
+ /* ram may contain useful data, save location before modifying */
+ tmp = *test_ptr;
+ *test_ptr = -1;
+ if (*mem_base == *test_ptr) {
+ *test_ptr = tmp;
+ res = 1;
+ break;
+ }
+ *test_ptr = tmp;
+ }
+ return res;
+}
+
+#define MEMC_MAX_ROWS 14
+
+int cfe_size_ram(void)
+{
+#if !(defined(_BCM96328_) || defined (_BCM96362_) || defined(_BCM96816_))
+ uint32 col_bits, row_bits, bus_bits, bank_bits;
+ uint32 size;
+
+ /* Bus width is configured during early boot */
+ if (((MEMC->Config & MEMC_WIDTH_MASK) >> MEMC_WIDTH_SHFT) == MEMC_32BIT_BUS)
+ bus_bits = 2;
+ else
+ bus_bits = 1;
+
+ bank_bits = 2;
+ /* Start from setting to the lowest possible configuration */
+ col_bits = 8;
+ row_bits = 11;
+
+ MEMC->Config &= ~MEMC_COL_MASK;
+ MEMC->Config |= ((col_bits - 8) << MEMC_COL_SHFT);
+
+ MEMC->Config &= ~MEMC_ROW_MASK;
+ MEMC->Config |= ((row_bits - 11) << MEMC_ROW_SHFT);
+
+ /* Determine number of rows */
+ for (row_bits = 12; row_bits <= MEMC_MAX_ROWS; row_bits++) {
+ MEMC->Config &= ~MEMC_ROW_MASK;
+ MEMC->Config |= ((row_bits - 11) << MEMC_ROW_SHFT);
+ /* check if this address bit is valid */
+ if (is_aliased (col_bits + row_bits + bus_bits + bank_bits))
+ break;
+ }
+ row_bits -= 1;
+ MEMC->Config &= ~MEMC_ROW_MASK;
+ MEMC->Config |= ((row_bits - 11) << MEMC_ROW_SHFT);
+
+ /* Determine number of columns */
+ for (col_bits = 9; col_bits <= 11; col_bits++) {
+ MEMC->Config &= ~MEMC_COL_MASK;
+ MEMC->Config |= ((col_bits - 8) << MEMC_COL_SHFT);
+ /* check if this address bit is valid */
+ if (is_aliased (col_bits + row_bits + bus_bits + bank_bits))
+ break;
+ }
+ col_bits -= 1;
+ MEMC->Config &= ~MEMC_COL_MASK;
+ MEMC->Config |= ((col_bits - 8) << MEMC_COL_SHFT);
+
+ /* Compute memory size in MB */
+ size = 1 << (bus_bits + col_bits + row_bits + bank_bits - 20);
+
+ return size;
+#else
+ return (DDR->CSEND << 24);
+#endif
+}
+
+// fake functions for not to modifying init_mips.S
+void _exc_entry(void);
+void cfe_command_restart(void);
+void cfe_doxreq(void);
+
+void _exc_entry(void)
+{
+}
+
+void cfe_command_restart(void)
+{
+}
+void cfe_doxreq(void)
+{
+}
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+void cfe_main(int,int);
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+void cfe_ledstr(const char *leds)
+{
+}
+
+#if !defined(CONFIG_BRCM_IKOS)
+extern void _binArrayStart(void);
+extern void _binArrayEnd(void);
+extern int decompressLZMA(unsigned char *in, unsigned insize, unsigned char *out, unsigned outsize);
+
+#if (INC_NAND_FLASH_DRIVER==1) || (INC_SPI_PROG_NAND==1)
+#define je16_to_cpu(x) ((x).v16)
+#define je32_to_cpu(x) ((x).v32)
+extern void rom_nand_flash_init(void);
+extern int nand_flash_get_sector_size(unsigned short sector);
+extern int nand_flash_get_numsectors(void);
+extern int nand_flash_read_buf(unsigned short blk, int offset,
+ unsigned char *buffer, int len);
+extern void board_setleds(unsigned long);
+
+void *lib_memcpy(void *dest,const void *src,size_t cnt)
+{
+ unsigned char *d;
+ const unsigned char *s;
+
+ d = (unsigned char *) dest;
+ s = (const unsigned char *) src;
+
+ while (cnt) {
+ *d++ = *s++;
+ cnt--;
+ }
+
+ return dest;
+}
+
+int lib_memcmp(const void *dest,const void *src,size_t cnt)
+{
+ const unsigned char *d;
+ const unsigned char *s;
+
+ d = (const unsigned char *) dest;
+ s = (const unsigned char *) src;
+
+ while (cnt) {
+ if (*d < *s) return -1;
+ if (*d > *s) return 1;
+ d++; s++; cnt--;
+ }
+
+ return 0;
+}
+
+#if (INC_NAND_FLASH_DRIVER==1)
+/* Find uncompressed file cferam.bin on the JFFS2 file system, load it into
+ * memory and jump to its entry point function.
+ */
+char g_fname[] = NAND_CFE_RAM_NAME;
+int g_fname_actual_len = sizeof(g_fname) - 1;
+int g_fname_cmp_len = sizeof(g_fname) - 4; /* last three are digits */
+static void bootImageFromNand(void)
+{
+ const unsigned long bv_invalid = 0xfffffff;
+ const int max_not_jffs2 = 10;
+
+ struct rootfs_info
+ {
+ int rootfs;
+ int start_blk;
+ int end_blk;
+ unsigned long boot_val;
+ unsigned long ino;
+ } rfs_info[2], *prfs_info[2], *rfsi;
+
+ unsigned char *buf = (unsigned char *) mem_heapstart;
+ unsigned long version = 0;
+ struct jffs2_raw_dirent *pdir;
+ struct jffs2_raw_inode *pino;
+ unsigned char *p;
+ int i, j, k, done, not_jffs2;
+ int num_blks;
+ int len;
+ int boot_prev;
+ PNVRAM_DATA nd;
+ static int err0=0, err1=1;
+
+ rom_nand_flash_init();
+ num_blks = nand_flash_get_numsectors();
+ len = nand_flash_get_sector_size(0);
+ nd = (PNVRAM_DATA) (buf + len);
+
+ NAND->NandNandBootConfig = NBC_AUTO_DEV_ID_CFG | 0x101;
+ NAND->NandCsNandXor = 1;
+
+ memcpy((unsigned char *) nd, (unsigned char *)
+ FLASH_BASE + NVRAM_DATA_OFFSET, sizeof(NVRAM_DATA));
+
+ NAND->NandNandBootConfig = NBC_AUTO_DEV_ID_CFG | 0x2;
+ NAND->NandCsNandXor = 0;
+
+ /* Look at config to determine whether to boot current or previous image.*/
+ for( i = 0, p = (unsigned char *) nd->szBootline, boot_prev = 0;
+ i < NVRAM_BOOTLINE_LEN; i++, p++ )
+ {
+ if( p[0] == ' ' && p[1] == 'p' && p[2] == '=' )
+ {
+ boot_prev = p[3] - '0';
+ if( boot_prev != 0 && boot_prev != 1 )
+ boot_prev = '0';
+ break;
+ }
+ }
+
+ /* Find the CFE ram inode entry point for both root file systems. */
+ board_setleds((boot_prev == 0) ? 0x4e414e30 : 0x4e414e31);
+ for( k = 0, rfsi = rfs_info; k < 2; k++, rfsi++ )
+ {
+ version = 0;
+ not_jffs2 = 0;
+ rfsi->rootfs = k + NP_ROOTFS_1;
+ rfsi->boot_val = bv_invalid;
+ if( nd->ulNandPartOfsKb[rfsi->rootfs] > 0 &&
+ nd->ulNandPartOfsKb[rfsi->rootfs] < ((num_blks * len) / 1024))
+ {
+ rfsi->start_blk = nd->ulNandPartOfsKb[rfsi->rootfs] / (len/1024);
+ rfsi->end_blk = rfsi->start_blk +
+ (nd->ulNandPartSizeKb[rfsi->rootfs] / (len / 1024));
+ }
+ else
+ rfsi->start_blk = rfsi->end_blk = 0;
+
+ if( rfsi->start_blk == 0 || rfsi->start_blk >= rfsi->end_blk ||
+ rfsi->start_blk >= num_blks || rfsi->end_blk >= num_blks )
+ {
+ /* NVRAM_DATA fields for this rootfs are not valid. */
+ if( k == 0 )
+ {
+ /* Skip this rootfs. */
+ board_setleds(0x4e414e36);
+ continue;
+ }
+
+ if( rfs_info[0].boot_val == bv_invalid )
+ {
+ /* File system info cannot be found for either rootfs.
+ * NVRAM_DATA may not be set. Use default values.
+ */
+ board_setleds(0x4e414e37);
+ rfsi = rfs_info;
+ rfsi->start_blk = 1;
+ rfsi->end_blk = num_blks;
+ }
+ }
+
+ /* Find the directory entry. */
+ for( i = rfsi->start_blk, done = 0; i < rfsi->end_blk && done == 0; i++ )
+ {
+ /* This loop sequentially reads a NAND flash block into memory and
+ * processes it.
+ */
+ if( nand_flash_read_buf(i, 0, buf, len) > 0 )
+ {
+ /* This loop reads inodes in a block. */
+ p = buf;
+ while( p < buf + len )
+ {
+ pdir = (struct jffs2_raw_dirent *) p;
+ if( je16_to_cpu(pdir->magic) == JFFS2_MAGIC_BITMASK )
+ {
+ if( je16_to_cpu(pdir->nodetype) ==
+ JFFS2_NODETYPE_DIRENT &&
+ g_fname_actual_len == pdir->nsize &&
+ !memcmp(g_fname, pdir->name, g_fname_cmp_len) )
+ {
+ /* The desired directory was found. */
+ if( je32_to_cpu(pdir->version) > version )
+ {
+ if( (rfsi->ino = je32_to_cpu(pdir->ino)) != 0 )
+ {
+ unsigned char *fname =
+ pdir->name + g_fname_cmp_len;
+ rfsi->boot_val =
+ ((fname[0] - '0') * 100) +
+ ((fname[1] - '0') * 10) +
+ ((fname[2] - '0') * 1);
+ version = je32_to_cpu(pdir->version);
+
+ board_setleds(0x42540000 +
+ ((unsigned long) fname[1] << 8) +
+ (unsigned long) fname[2]);
+
+ /* Setting 'done = 1' assumes there is only
+ * one version of the directory entry. This
+ * may not be correct if the file is
+ * updated after it was initially flashed.
+ *
+ * TBD. Look for a higher version of the
+ * directory entry without searching the
+ * entire flash part.
+ */
+ done = 1;
+ break;
+ }
+ }
+ }
+
+ p += (je32_to_cpu(pdir->totlen) + 0x03) & ~0x03;
+ not_jffs2 = 0;
+ }
+ else
+ {
+ if( not_jffs2++ > max_not_jffs2 )
+ {
+ /* No JFFS2 magic bitmask for consecutive blocks.
+ * Assume this partion does not have a file system
+ * on it.
+ */
+ board_setleds(0x53544F50);
+ done = 1;
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ if(!err0)
+ {
+ err0=1;
+ board_setleds(0x45525230);
+ }
+ }
+ }
+ board_setleds(0x4e414e39);
+ }
+
+ /* Set the rfs_info to the index to boot from. */
+ if( (boot_prev == 0 && rfs_info[0].boot_val > rfs_info[1].boot_val) ||
+ (boot_prev == 1 && rfs_info[0].boot_val < rfs_info[1].boot_val) ||
+ rfs_info[1].boot_val == bv_invalid )
+ {
+ /* Boot from the most recent image. */
+ prfs_info[0] = &rfs_info[0];
+ prfs_info[1] = &rfs_info[1];
+ }
+ else
+ {
+ /* Boot from the previous image. */
+ prfs_info[0] = &rfs_info[1];
+ prfs_info[1] = &rfs_info[0];
+ }
+
+ /* If the directory entry for the desired file, which is the CFE RAM image,
+ * is found, read it into memory and jump to its entry point function.
+ * This loop checks for CFE RAM image in two possible rootfs file sytems.
+ */
+ for( k = 0; k < 2; k++ )
+ {
+ unsigned char *pucDest = NULL;
+ unsigned char *pucEntry = NULL;
+ long isize = 0;
+
+ board_setleds(0x4e414e33);
+ rfsi = prfs_info[k];
+ if( rfsi->boot_val == bv_invalid )
+ continue;
+
+ /* When j == 0, get the first inode to find the entry point address.
+ * When j == 1, read the file contents into memory.
+ */
+ for( j = 0; j < 2; j++ )
+ {
+ /* This loop sequentially reads a NAND flash block into memory and
+ * processes it.
+ */
+ for(i = rfsi->start_blk, done = 0; i<rfsi->end_blk && done==0; i++)
+ {
+ if( nand_flash_read_buf(i, 0, buf, len) > 0 )
+ {
+ /* This loop reads inodes in a block. */
+ p = buf;
+ while( p < buf + len )
+ {
+ /* Verify the first short word is the JFFS2 magic
+ * number.
+ */
+ pino = (struct jffs2_raw_inode *) p;
+ if( je16_to_cpu(pino->magic) == JFFS2_MAGIC_BITMASK )
+ {
+ if( je16_to_cpu(pino->nodetype) ==
+ JFFS2_NODETYPE_INODE &&
+ je32_to_cpu(pino->ino) == rfsi->ino )
+ {
+ unsigned long size = je32_to_cpu(pino->dsize);
+ unsigned long ofs = je32_to_cpu(pino->offset);
+
+ if( size )
+ {
+ /* A node of the CFE RAM file was found
+ * with data. */
+ if( pucDest == NULL )
+ {
+ /* The entry point and copy destination
+ * addresses have not been obtained.
+ * If this is the first node of the CFE
+ * RAM file, obtain this information.
+ */
+ if( ofs == 0 )
+ {
+ /* The first 12 bytes contain a
+ * header. The first word is the
+ * entry point address.
+ */
+ pucEntry = (unsigned char *)
+ *(unsigned long *) pino->data;
+ pucDest = pucEntry - 12;
+ isize = je32_to_cpu(pino->isize);
+ done = 1;
+ board_setleds(0x52465330 |
+ rfsi->rootfs);
+ break;
+ }
+ }
+ else
+ {
+ /* Copy the image to memory. Stop when
+ * the entire image has been copied.
+ */
+ memcpy(pucDest+ofs, pino->data, size);
+ if( (isize -= size) <= 0 )
+ {
+ done = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Skip to the next inode entry. */
+ p += (je32_to_cpu(pino->totlen) + 0x03) & ~0x03;
+ }
+ else
+ break;
+ }
+ }
+ else
+ {
+ if(!err1)
+ {
+ err1=1;
+ board_setleds(0x45525231);
+ }
+ }
+ }
+ }
+
+ if( pucEntry && isize <= 0 )
+ {
+ board_setleds(0x4e414e35);
+
+ /* Save the rootfs partition that the CFE RAM image boots from
+ * at the memory location before the CFE RAM load address. The
+ * CFE RAM image uses this value to determine the partition to
+ * flash a new rootfs to.
+ */
+ *(pucEntry - 1) = (unsigned char) rfsi->rootfs;
+
+ cfe_launch((unsigned long) pucEntry); // never return...
+ }
+ board_setleds(0x4e414e38);
+ }
+
+ /* Error occurred. */
+ board_setleds(0x44494530);
+ while(1);
+}
+#endif
+#endif
+
+/* *********************************************************************
+ * cfe_main(a,b)
+ *
+ * It's gotta start somewhere.
+ * Input parameters:
+ * a,b - not used
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+void cfe_main(int a,int b)
+{
+ unsigned char *pucSrc;
+ unsigned char *pucDst;
+ unsigned int *entryPoint;
+ unsigned int binArrayStart = (unsigned int) _binArrayStart;
+ unsigned int binArrayEnd = (unsigned int) _binArrayEnd;
+ unsigned int dataLen = binArrayEnd - binArrayStart - 4;
+ int ret;
+
+ KMEMINIT((unsigned char *) (uint32_t) mem_heapstart,
+ ((CFG_HEAP_SIZE)*1024));
+
+#if (INC_NAND_FLASH_DRIVER==1) && (defined(_BCM96816_) || defined(_BCM96362_) || defined(_BCM96328_))
+ if( ((MISC->miscStrapBus & MISC_STRAP_BUS_BOOT_SEL_MASK) >>
+ MISC_STRAP_BUS_BOOT_SEL_SHIFT) == MISC_STRAP_BUS_BOOT_NAND )
+ {
+ bootImageFromNand(); /* Will not return. */
+ }
+#elif (INC_NAND_FLASH_DRIVER==1) && defined(_BCM96368_)
+ if( ((GPIO->StrapBus & MISC_STRAP_BUS_BOOT_SEL_MASK) >>
+ MISC_STRAP_BUS_BOOT_SEL_SHIFT) == MISC_STRAP_BUS_BOOT_NAND )
+ {
+ bootImageFromNand(); /* Will not return. */
+ }
+#endif
+
+ entryPoint = (unsigned int*) binArrayStart;
+ pucSrc = (unsigned char *) (binArrayStart + 4);
+
+ pucDst = (unsigned char *) *entryPoint;
+ ret = decompressLZMA((unsigned char*)pucSrc,
+ (unsigned int)dataLen,
+ (unsigned char *) pucDst,
+ 23*1024*1024);
+
+ if (ret != 0)
+ while (1); // if not decompressed ok, loop for EJTAG
+
+ cfe_launch((unsigned long) pucDst); // never return...
+}
+#else
+/* 0x694b6f31 (iKo1) is replaced with actual address during the build process.*/
+unsigned long cfeRamStartAddr=0x694b6f31;
+void cfe_main(int a,int b)
+{
+ cfe_size_ram();
+ cfe_launch(cfeRamStartAddr); // never return...
+}
+#endif
+
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_rom/src/memtest.c b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/memtest.c
new file mode 100755
index 0000000..310fb40
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/memtest.c
@@ -0,0 +1,1031 @@
+/*
+ *----------------------------------------------------------------------------*
+ * Collection of Memory Tests.
+ *----------------------------------------------------------------------------*
+ */
+
+//
+// NOTE: Blatant inlining ... (not sure whether caller supports EABI calls).
+// WARNING CFE: Must NOT use function calls !!!
+//
+#define _ALWAYS_INLINE_ __attribute__((always_inline))
+#define _INLINE_ inline static
+
+typedef enum memTestResult {
+ MEMTEST_FAILURE = 0,
+ MEMTEST_SUCCESS,
+ MEMTEST_ERROR,
+} MemTestResult_t;
+
+/* ------------------------------------------------------------------------- */
+
+#undef PATTERN
+#define PATTERN(x) PATTERN_##x,
+
+/*
+ * For each pattern listed, the inverse pattern is also automatically used.
+ * E.g. 0x55555555, the inverse of defined 0xAAAAAAAA is covered.
+ */
+typedef enum pattern {
+ PATTERN(0x00000000)
+ PATTERN(0xAAAAAAAA)
+ PATTERN(0xCCCCCCCC)
+ PATTERN(0x77777777)
+ PATTERN(0xF0F0F0F0)
+ PATTERN(0xFF00FF00)
+ PATTERN(0xFFFF0000)
+ PATTERN(0x01234567)
+ PATTERN(0x89ABCDEF)
+ PATTERN_MAX,
+} Pattern_t;
+
+#undef PATTERN
+#define PATTERN(x) x,
+const uint32_t pattern[] = {
+ PATTERN(0x00000000)
+ PATTERN(0xAAAAAAAA)
+ PATTERN(0xCCCCCCCC)
+ PATTERN(0x77777777)
+ PATTERN(0xF0F0F0F0)
+ PATTERN(0xFF00FF00)
+ PATTERN(0xFFFF0000)
+ PATTERN(0x01234567)
+ PATTERN(0x89ABCDEF)
+ PATTERN_MAX,
+};
+
+/* ------------------------------------------------------------------------- */
+
+#ifndef NBBY
+#define NBBY 8 /* FreeBSD style: Number Bits per BYte */
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+#define NBITS(type) (sizeof(type) * NBBY)
+#define NBITVAL(nbits) (1 << (nbits))
+#define MAXBITVAL(nbits) ( NBITVAL(nbits) - 1)
+#define NBITMASK(nbits) MAXBITVAL(nbits)
+#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * NBBY)
+
+#define DIVBY(val32,by) ((val32)>>(by))
+#define MODBY(val32,by) ((val32) & ((1 <<(by)) - 1) )
+
+#define IS_POWEROF2(val32) ( (((val32)-1) & (val32)) == 0 )
+
+#define ROUNDDN(addr, align) ( (addr) & ~((align) - 1) )
+#define ROUNDUP(addr, align) ( ((addr) + (align) - 1) & ~((align) - 1) )
+//#define ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y))
+#define ALIGN_ADDR(addr, bytes) (void *)( ((uint32_t *)(addr) + (bytes) - 1) \
+ & ~((bytes) - 1) )
+#define IS_ALIGNED(addr, bytes) (((uint32_t)(addr) & ((bytes)-1)) == 0)
+
+#define OFFSET_OF(stype,member) ((uint32_t) &((struct stype *)0)->member)
+#define RELOC(base,stype,member) ((base) + OFFSET_OF(stype, member))
+
+#define RROTATE32(val32) (((val32) << 31) | ((val32) >> 1))
+#define LROTATE32(val32) (((val32) << 1) | ((val32) >> 31))
+
+/* ------------------------------------------------------------------------- */
+
+/* Aligned (32bit register) read/write access */
+#define RD16(addr16) (*(volatile uint32_t *)(addr16))
+#define WR16(addr16,val16) (*(volatile uint32_t *)(addr16))=(val16)
+#define RD32(addr32) (*(volatile uint32_t *)(addr32))
+#define WR32(addr32,val32) (*(volatile uint32_t *)(addr32))=(val32)
+
+/*---------------------------------------------------------------------------*/
+
+/* Forward declaration */
+_INLINE_ void fill_memory( uint32_t * addr, uint32_t bytes, uint32_t fill32)
+ _ALWAYS_INLINE_;
+_INLINE_ void fill_alt_memory(uint32_t * addr, uint32_t bytes,
+ uint32_t fillA32, uint32_t fillB32) _ALWAYS_INLINE_;
+
+void fill_memory( uint32_t * addr, uint32_t bytes, uint32_t fill32)
+{
+ uint32_t * at, * end_p;
+ uint32_t words;
+ words = bytes / sizeof(uint32_t);
+ if ( words == 0 ) return;
+
+ end_p = addr + words;
+ for ( at = addr; at < end_p; at++ )
+ WR32( at, fill32 );
+}
+
+void fill_alt_memory( uint32_t * addr, uint32_t bytes,
+ uint32_t fillA32, uint32_t fillB32)
+{
+ uint32_t * at, * end_p;
+ uint32_t words;
+ words = bytes / sizeof(uint32_t);
+ words = ROUNDDN( words, 2 );
+ if ( words == 0 ) return;
+
+ end_p = addr + words;
+ for ( at = addr; at < end_p; at+=2 )
+ {
+ WR32( at+0, fillA32 );
+ WR32( at+1, fillB32 );
+ }
+}
+
+/* Forward declaration */
+_INLINE_ MemTestResult_t scanWordValue( uint32_t * addr, uint32_t bytes,
+ uint32_t pat32 ) _ALWAYS_INLINE_;
+_INLINE_ MemTestResult_t scanBulkValue( uint32_t * addr, uint32_t bytes,
+ uint32_t pat32 ) _ALWAYS_INLINE_;
+_INLINE_ MemTestResult_t scanBulkAltInv( uint32_t * addr, uint32_t bytes,
+ uint32_t pat32 ) _ALWAYS_INLINE_;
+_INLINE_ MemTestResult_t scanWordSelf( uint32_t * addr, uint32_t bytes )
+ _ALWAYS_INLINE_;
+_INLINE_ MemTestResult_t scanBulkSelf( uint32_t * addr, uint32_t bytes )
+ _ALWAYS_INLINE_;
+_INLINE_ MemTestResult_t slidingAltInv( uint32_t * addr, uint32_t bytes,
+ uint32_t pat32 ) _ALWAYS_INLINE_;
+_INLINE_ MemTestResult_t slidingDiag( uint32_t * addr, uint32_t bytes,
+ uint32_t pat32 ) _ALWAYS_INLINE_;
+_INLINE_ MemTestResult_t memoryBulkCopy( uint32_t * saddr, uint32_t * daddr,
+ uint32_t bytes ) _ALWAYS_INLINE_;
+
+/*
+ *-----------------------------------------------------------------------------
+ * Function: scanWordValue
+ *
+ * Description:
+ * 4 Passes are conducted on the memory region.
+ * Pass 1. In INcreasing memory address, write a word with value and verify.
+ * Pass 2. In DEcreasing memory address, write a word with value and verify.
+ * Pass 3. In INcreasing memory address, write a word with INVERSE and verify.
+ * Pass 4. In DEcreasing memory address, write a word with INVERSE and verify.
+ * Pass 5. In INcreasing shifted memory address, write word with value verify.
+ * Pass 6. In INcreasing shifted memory address, write word with INVERSE verify.
+ *
+ * Parameters:
+ * addr: word aligned pointer to memory region
+ * bytes: size in bytes of memory region to test
+ * pat32: 32bit pattern, e.g. 0x0U, 0xAAAAAAAA, 0xFF00FF00, 0xFFFF0000,
+ * 0xF0F0F0F0, 0xC3C3C3C3, 0x87878787
+ *-----------------------------------------------------------------------------
+ */
+MemTestResult_t scanWordValue( uint32_t * addr, uint32_t bytes, uint32_t pat32 )
+{
+ volatile uint32_t * at, * end_p;
+ uint32_t expected, read, words;
+ uint32_t shift;
+
+ if ( ! IS_ALIGNED(addr,4) ) return MEMTEST_ERROR;
+
+ words = bytes / sizeof(uint32_t); /* in whole words (4byte multiple) */
+ if ( words == 0 )
+ return MEMTEST_ERROR;
+
+ expected = pat32; /* ORIGINAL value */
+
+ /* INCREASING traversal */
+ end_p = addr + words;
+ for ( at = addr; at < end_p; at++ )
+ {
+ WR32( at, expected );
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* DECREASING traversal */
+ end_p = addr;
+ for ( at = addr + words - 1; at >= end_p; at-- )
+ {
+ WR32( at, expected );
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ expected = ~pat32; /* INVERSE value */
+
+ /* INCREASING traversal */
+ end_p = addr + words;
+ for ( at = addr; at < end_p; at++ )
+ {
+ WR32( at, expected );
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* DECREASING traversal */
+ end_p = addr;
+ for ( at = addr + words - 1; at >= end_p; at-- )
+ {
+ WR32( at, expected );
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* PASS 5: Shifting address walk, ORIGINAL */
+ expected = pat32; /* ORIGINAL value */
+
+ end_p = addr + words;
+ shift = sizeof(uint32_t);
+ for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift )
+ {
+ WR32( at, expected );
+ WR32( addr, ~expected ); /* noise at base addr */
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ expected = ~pat32; /* INVERSE value */
+
+ /* PASS 6: Shifting address walk, INVERSE */
+ end_p = addr + words;
+ shift = sizeof(uint32_t);
+ for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift )
+ {
+ WR32( at, expected );
+ WR32( addr, ~expected ); /* noise at base addr */
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ return MEMTEST_SUCCESS;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * Function: scanBulkValue
+ *
+ * Description:
+ * Pass 1. Fill entire memory in INcreasing memory address with value
+ * then in INcreasing memory address read and verify.
+ * Pass 2. Fill entire memory in DEcreasing memory address with value
+ * then in DEcreasing memory address read and verify.
+ * Pass 3. Fill entire memory in INcreasing memory address with inverse value
+ * then in INcreasing memory address read and verify.
+ * Pass 4. Fill entire memory in DEcreasing memory address with inverse value
+ * then in DEcreasing memory address read and verify.
+ * Pass 5. INcreasing shifted, ORIGINAL
+ * Pass 6. INcreasing shifted, INVERSE
+ *
+ * Parameters:
+ * addr: word aligned pointer to memory region
+ * bytes: size in bytes of memory region to test
+ * pat32: 32bit pattern, e.g. 0x0U, 0xAAAAAAAA, 0xFF00FF00, 0xFFFF0000,
+ * 0xF0F0F0F0, 0xC3C3C3C3, 0x87878787
+ *-----------------------------------------------------------------------------
+ */
+MemTestResult_t scanBulkValue( uint32_t * addr, uint32_t bytes, uint32_t pat32 )
+{
+ volatile uint32_t * at, * end_p;
+ uint32_t expected, read, words;
+ uint32_t shift;
+
+ if ( ! IS_ALIGNED(addr,4) ) return MEMTEST_ERROR;
+
+ words = bytes / sizeof(uint32_t); /* in whole words (4byte multiple) */
+ if ( words == 0 ) return MEMTEST_ERROR;
+
+ expected = pat32; /* ORIGINAL value */
+
+ /* INCREASING traversal */
+ end_p = addr + words;
+ for ( at = addr; at < end_p; at++ )
+ {
+ WR32( at, expected );
+ }
+ for ( at = addr; at < end_p; at++ )
+ {
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* DECREASING traversal */
+ end_p = addr;
+ for ( at = addr + words - 1; at >= end_p; at-- )
+ {
+ WR32( at, expected );
+ }
+ for ( at = addr + words - 1; at >= end_p; at-- )
+ {
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ expected = ~pat32; /* INVERSE value */
+
+ /* INCREASING traversal */
+ end_p = addr + words;
+ for ( at = addr; at < end_p; at++ )
+ {
+ WR32( at, expected );
+ }
+ for ( at = addr; at < end_p; at++ )
+ {
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* DECREASING traversal */
+ end_p = addr;
+ for ( at = addr + words - 1; at >= end_p; at-- )
+ {
+ WR32( at, expected );
+ }
+ for ( at = addr + words - 1; at >= end_p; at-- )
+ {
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* Pass 5. INCREASING Shifted traversal */
+ expected = pat32; /* ORIGINAL value */
+ end_p = addr + words;
+ shift = sizeof(uint32_t);
+ for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift )
+ {
+ WR32( at, expected );
+ WR32( addr, ~expected ); /* noise at base addr */
+ }
+ shift = sizeof(uint32_t);
+ for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift )
+ {
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ expected = ~pat32; /* INVERSE value */
+ end_p = addr + words;
+ shift = sizeof(uint32_t);
+ for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift )
+ {
+ WR32( at, expected );
+ WR32( addr, ~expected ); /* noise at base addr */
+ }
+ shift = sizeof(uint32_t);
+ for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift )
+ {
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ return MEMTEST_SUCCESS;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * Function: scanBulkAltInv
+ *
+ * Description:
+ * Pass 1. Fill entire memory in INcreasing memory address with alternating
+ * value, then in INcreasing memory address read and verify.
+ * Pass 2. Fill entire memory in DEcreasing memory address with alternating
+ * value, then in DEcreasing memory address read and verify.
+ * Pass 3. Same as one but with shifted address.
+ *
+ * Parameters:
+ * addr: word aligned pointer to memory region
+ * bytes: size in bytes of memory region to test
+ * pat32: 32bit pattern, e.g. 0x0U, 0xAAAAAAAA, 0xFF00FF00, 0xFFFF0000,
+ * 0xF0F0F0F0, 0xC3C3C3C3, 0x87878787
+ *-----------------------------------------------------------------------------
+ */
+MemTestResult_t scanBulkAltInv( uint32_t * addr, uint32_t bytes, uint32_t pat32 )
+{
+ volatile uint32_t * at, * end_p;
+ uint32_t read, words;
+ uint32_t shift;
+
+ if ( ! IS_ALIGNED(addr,4) ) return MEMTEST_ERROR;
+
+ words = bytes / sizeof(uint32_t); /* in whole words (4byte multiple) */
+ words = ROUNDDN( words, 2 );
+ if ( words == 0 ) return MEMTEST_ERROR;
+
+ /* INCREASING traversal */
+ end_p = addr + words;
+ for ( at = addr; at < end_p; at+=2 )
+ {
+ WR32( at+0, pat32 );
+ WR32( at+1, ~pat32 );
+ }
+ for ( at = addr; at < end_p; at+=2 )
+ {
+ read = RD32( at+0 );
+ if ( read != pat32 )
+ {
+ return MEMTEST_FAILURE;
+ }
+ read = RD32( at+1 );
+ if ( read != ~pat32 )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* DECREASING traversal */
+ end_p = addr;
+ for ( at = addr + words - 1; at >= end_p; at-=2 )
+ {
+ WR32( at+0, pat32 );
+ WR32( at+1, ~pat32 );
+ }
+ for ( at = addr + words - 1; at >= end_p; at-=2 )
+ {
+ read = RD32( at+0 );
+ if ( read != pat32 )
+ {
+ return MEMTEST_FAILURE;
+ }
+ read = RD32( at+1 );
+ if ( read != ~pat32 )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* INCREASING SHIFTED traversal */
+ end_p = addr + words;
+ shift = sizeof(uint32_t);
+ for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift )
+ {
+ WR32( at+0, pat32 );
+ WR32( addr, 0 );
+ WR32( at+1, ~pat32 );
+ WR32( addr, 0 );
+ }
+ shift = sizeof(uint32_t);
+ for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift )
+ {
+ read = RD32( at+0 );
+ if ( read != pat32 )
+ {
+ return MEMTEST_FAILURE;
+ }
+ read = RD32( at+1 );
+ if ( read != ~pat32 )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ return MEMTEST_SUCCESS;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ * Function: scanWordSelf
+ *
+ * Description:
+ * 4 Passes are conducted on the memory region.
+ * Pass 1. In INcreasing memory address, write a word with selfaddr and verify.
+ * Pass 2. In DEcreasing memory address, write a word with INVERSE and verify.
+ * Pass 3. In INcreasing memory address, write a word with INVERSE and verify.
+ * Pass 4. In DEcreasing memory address, write a word with selfaddr and verify.
+ * Pass 5. value = ORIGINAL address, INCREASING SHIFTED traversal.
+ * Pass 6. value = INVERSE address, INCREASING SHIFTED traversal.
+ *
+ * In Pass 2 Read+Modify+Write, and in Pass 3, Read+Write is used
+ *
+ * Parameters:
+ * addr: word aligned pointer to memory region
+ * bytes: size in bytes of memory region to test
+ *
+ *-----------------------------------------------------------------------------
+ */
+MemTestResult_t scanWordSelf( uint32_t * addr, uint32_t bytes )
+{
+ volatile uint32_t * at, * end_p;
+ uint32_t expected, read, words;
+ uint32_t shift;
+
+ if ( ! IS_ALIGNED(addr,4) ) return MEMTEST_FAILURE;
+
+ words = bytes / sizeof(uint32_t); /* in whole words (4byte multiple) */
+ if ( words == 0 ) return MEMTEST_ERROR;
+
+ /* ORIGINAL value */
+
+ /* INCREASING traversal */
+ end_p = addr + words;
+ for ( at = addr; at < end_p; at++ )
+ {
+ expected = (uint32_t)at;
+ WR32( at, expected );
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* DECREASING traversal */
+ end_p = addr;
+ for ( at = addr + words - 1; at >= end_p; at-- )
+ {
+ expected = ~( (uint32_t)RD32(at) );
+ WR32( at, expected );
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* INCREASING traversal */
+ end_p = addr + words;
+ for ( at = addr; at < end_p; at++ )
+ {
+ expected = ((uint32_t)RD32(at));
+ WR32( at, expected );
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* DECREASING traversal */
+ end_p = addr;
+ for ( at = addr + words - 1; at >= end_p; at-- )
+ {
+ expected = ~((uint32_t)at);
+ WR32( at, expected );
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* value = ORIGINAL address, INCREASING SHIFTED traversal */
+ end_p = addr + words;
+ shift = sizeof(uint32_t);
+ for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift )
+ {
+ expected = (uint32_t)at; /* Not read modify write */
+ WR32( at, expected );
+ WR32( addr, ~expected );
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* value = INVERSE address, INCREASING SHIFTED traversal */
+ end_p = addr + words;
+ shift = sizeof(uint32_t);
+ for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift )
+ {
+ expected = ~(uint32_t)(at); /* Not read modify write */
+ WR32( at, expected );
+ WR32( addr, ~expected );
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ return MEMTEST_SUCCESS;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * Function: scanBulkSelf
+ *
+ * Description:
+ * Pass 1. Fill entire memory in INcreasing memory address with self address
+ * then in INcreasing memory address read and verify.
+ * Pass 2. Fill entire memory in DEcreasing memory address with self address
+ * then in DEcreasing memory address read and verify.
+ * Pass 3. Fill entire memory in INcreasing memory address with inverse addr
+ * then in INcreasing memory address read and verify.
+ * Pass 4. Fill entire memory in DEcreasing memory address with inverse addr
+ * then in DEcreasing memory address read and verify.
+ * Pass 5. Same as Pass 1 but with shifted address
+ * Pass 6. Same as Pass 3 but with shifted address
+ *
+ * Parameters:
+ * addr: word aligned pointer to memory region
+ * bytes: size in bytes of memory region to test
+ *-----------------------------------------------------------------------------
+ */
+MemTestResult_t scanBulkSelf( uint32_t * addr, uint32_t bytes )
+{
+ volatile uint32_t * at, * end_p;
+ uint32_t read, words;
+ uint32_t shift;
+
+ if ( ! IS_ALIGNED(addr,4) ) return MEMTEST_ERROR;
+
+ words = bytes / sizeof(uint32_t); /* in whole words (4byte multiple) */
+ if ( words == 0 ) return MEMTEST_ERROR;
+
+ /* INCREASING traversal */
+ end_p = addr + words;
+ for ( at = addr; at < end_p; at++ )
+ {
+ WR32( at, (uint32_t)at );
+ }
+ for ( at = addr; at < end_p; at++ )
+ {
+ read = RD32(at);
+ if ( read != (uint32_t)at )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* DECREASING traversal */
+ end_p = addr;
+ for ( at = addr + words - 1; at >= end_p; at-- )
+ {
+ WR32( at, (uint32_t)at );
+ }
+ for ( at = addr + words - 1; at >= end_p; at-- )
+ {
+ read = RD32(at);
+ if ( read != (uint32_t)at )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* INCREASING traversal */
+ end_p = addr + words;
+ for ( at = addr; at < end_p; at++ )
+ {
+ WR32( at, ~((uint32_t)at) );
+ }
+ for ( at = addr; at < end_p; at++ )
+ {
+ read = RD32(at);
+ if ( read != ~((uint32_t)at) )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* DECREASING traversal */
+ end_p = addr;
+ for ( at = addr + words - 1; at >= end_p; at-- )
+ {
+ WR32( at, ~((uint32_t)at) );
+ }
+ for ( at = addr + words - 1; at >= end_p; at-- )
+ {
+ read = RD32(at);
+ if ( read != ~((uint32_t)at) )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* INCREASING traversal */
+ end_p = addr + words;
+ shift = sizeof(uint32_t);
+ for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift )
+ {
+ WR32( at, (uint32_t)at );
+ WR32( addr, ~((uint32_t)at) );
+ }
+ shift = sizeof(uint32_t);
+ for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift )
+ {
+ read = RD32(at);
+ if ( read != (uint32_t)at )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* INCREASING traversal */
+ end_p = addr + words;
+ shift = sizeof(uint32_t);
+ for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift )
+ {
+ WR32( at, ~((uint32_t)at) );
+ WR32( addr, ((uint32_t)at) );
+ }
+ shift = sizeof(uint32_t);
+ for ( at = addr + shift; at < end_p; shift <<= 1, at = addr + shift )
+ {
+ read = RD32(at);
+ if ( read != ~((uint32_t)at) )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ return MEMTEST_SUCCESS;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ * Function: slidingAltInv
+ *
+ * Description:
+ * This is the same as scanBulkAltInv, where in each invocation the value is
+ * rotated to the right. The starting value is usedefined.
+ *
+ * Parameters:
+ * addr: word aligned pointer to memory region
+ * bytes: size in bytes of memory region to test
+ * pat32: pattern to slide per pass
+ *-----------------------------------------------------------------------------
+ */
+MemTestResult_t slidingAltInv( uint32_t * addr, uint32_t bytes, uint32_t pat32 )
+{
+ uint32_t sliding_pat32, i;
+
+ if ( pat32 == 0x0 ) pat32 = 0x80000000;
+ if ( pat32 == ~0x0 ) pat32 = 0x7FFFFFFF;
+
+ sliding_pat32 = pat32;
+
+ for ( i=0; i<32; i++ )
+ {
+ if ( scanBulkAltInv( addr, bytes, sliding_pat32 )
+ == MEMTEST_FAILURE )
+ {
+ return MEMTEST_FAILURE;
+ }
+
+ sliding_pat32 = RROTATE32( sliding_pat32 );
+ }
+
+ sliding_pat32 = pat32;
+ for (i=0; i<32; i++)
+ {
+ if ( scanBulkAltInv( addr, bytes, sliding_pat32 )
+ == MEMTEST_FAILURE )
+ {
+ return MEMTEST_FAILURE;
+ }
+
+ sliding_pat32 = LROTATE32( sliding_pat32 );
+ }
+
+ return MEMTEST_SUCCESS;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * Function: slidingDiag
+ *
+ * Description:
+ * Pass 1. Fill entire memory in INcreasing memory address with pattern right
+ * shifted. Then read in INcreasing order and verify.
+ * Pass 2. Fill entire memory in DEcreasing memory address with inverse of
+ * read value. Then read in DEcreasing order and verify.
+ * Pass 3. Fill entire memory in DEcreasing memory address with pattern right
+ * shifted. Then read in DEcreasing order and verify.
+ * Pass 4. Fill entire memory in INcreasing memory address with inverse of
+ * read value. Then read in INcreasing order and verify.
+ *
+ * Parameters:
+ * addr: word aligned pointer to memory region
+ * bytes: size in bytes of memory region to test
+ * pat32: pattern to be filled shifted each write
+ *-----------------------------------------------------------------------------
+ */
+MemTestResult_t slidingDiag( uint32_t * addr, uint32_t bytes, uint32_t pat32 )
+{
+ volatile uint32_t * at, * end_p;
+ uint32_t expected, read = 0, words, last;
+
+ if ( ! IS_ALIGNED(addr,4) ) return MEMTEST_ERROR;
+
+ words = bytes / sizeof(uint32_t); /* in whole words (4byte multiple) */
+ if ( words == 0 ) return MEMTEST_ERROR;
+
+
+ /* INCREASING traversal */
+ expected = pat32; /* ORIGINAL value */
+ end_p = addr + words;
+ for ( at = addr; at < end_p; at++ )
+ {
+ WR32( at, expected );
+ expected = RROTATE32( expected ); /* next expected */
+ }
+ expected = pat32; /* ORIGINAL value */
+ for ( at = addr; at < end_p; at++ )
+ {
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ expected = RROTATE32( expected ); /* next expected */
+ }
+
+ last = ~( read ); /* Starting value for decreasing traversal, next */
+
+ /* DECREASING traversal */
+ end_p = addr;
+ for ( at = addr + words - 1; at >= end_p; at-- )
+ {
+ expected = ~( RD32(at) );
+ WR32( at, expected );
+ }
+ expected = last;
+ for ( at = addr + words - 1; at >= end_p; at-- )
+ {
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ expected = LROTATE32( expected );
+ }
+
+ /* DECREASING traversal */
+ expected = pat32; /* ORIGINAL value */
+ end_p = addr;
+ for ( at = addr + words - 1; at >= end_p; at-- )
+ {
+ WR32( at, expected );
+ expected = RROTATE32( expected ); /* next expected */
+ }
+ expected = pat32; /* ORIGINAL value */
+ for ( at = addr + words - 1; at >= end_p; at-- )
+ {
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ expected = RROTATE32( expected ); /* next expected */
+ }
+
+ last = ~( read );
+
+ /* INCREASING traversal */
+ end_p = addr + words;
+ for ( at = addr; at < end_p; at++ )
+ {
+ expected = ~( RD32(at) );
+ WR32( at, expected );
+ }
+ expected = last;
+ for ( at = addr; at < end_p; at++ )
+ {
+ read = RD32(at);
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ expected = LROTATE32( expected );
+ }
+
+ return MEMTEST_SUCCESS;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * Function: memoryBulkCopy
+ *
+ * Description:
+ * Pass 1. Copy entire ORIGINAL memory in INcreasing memory address, then verify
+ * Pass 2. Copy entire ORIGINAL memory in DEcreasing memory address, then verify
+ * Pass 3. Copy entire INVERSE memory in INcreasing memory address, then verify
+ * Pass 4. Copy entire INVERSE memory in DEcreasing memory address, then verify
+ *-----------------------------------------------------------------------------
+ */
+MemTestResult_t memoryBulkCopy( uint32_t * saddr, uint32_t * daddr,
+ uint32_t bytes )
+{
+ volatile uint32_t * src_p, * dst_p, * end_p;
+ uint32_t expected, read, words;
+
+ if ( ! IS_ALIGNED(saddr,4) ) return MEMTEST_ERROR;
+ if ( ! IS_ALIGNED(daddr,4) ) return MEMTEST_ERROR;
+
+ words = bytes / sizeof(uint32_t); /* in whole words (4byte multiple) */
+ if ( words == 0 ) return MEMTEST_ERROR;
+
+ if ( (uint32_t)saddr < (uint32_t)daddr )
+ {
+ if ( (uint32_t)(saddr + words) > (uint32_t)daddr )
+ return MEMTEST_ERROR;
+ }
+ else if ( (uint32_t)daddr < (uint32_t)saddr )
+ {
+ if ( (uint32_t)(daddr + words) > (uint32_t)saddr )
+ return MEMTEST_ERROR;
+ }
+
+ /* INCREASING traversal ORIGINAL */
+ end_p = saddr + words;
+ for ( src_p = saddr, dst_p = daddr; src_p < end_p; src_p++, dst_p++ )
+ {
+ expected = RD32( dst_p );
+ WR32( src_p, expected );
+ }
+ for ( src_p = saddr, dst_p = daddr; src_p < end_p; src_p++, dst_p++ )
+ {
+ expected = RD32( dst_p );
+ read = RD32( src_p );
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* DECREASING traversal ORIGINAL */
+ end_p = saddr;
+ for ( src_p = saddr + words - 1, dst_p = daddr + words - 1;
+ src_p >= end_p; src_p--, dst_p-- )
+ {
+ expected = RD32( dst_p );
+ WR32( src_p, expected );
+ }
+ for ( src_p = saddr + words - 1, dst_p = daddr + words - 1;
+ src_p >= end_p; src_p--, dst_p-- )
+ {
+ expected = RD32( dst_p );
+ read = RD32( src_p );
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* INCREASING traversal INVERSE */
+ end_p = saddr + words;
+ for ( src_p = saddr, dst_p = daddr; src_p < end_p; src_p++, dst_p++ )
+ {
+ expected = ~( RD32( dst_p ) );
+ WR32( src_p, expected );
+ }
+ for ( src_p = saddr, dst_p = daddr; src_p < end_p; src_p++, dst_p++ )
+ {
+ expected = ~( RD32( dst_p ) );
+ read = RD32( src_p );
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ /* DECREASING traversal INVERSE */
+ end_p = saddr;
+ for ( src_p = saddr + words - 1, dst_p = daddr + words - 1;
+ src_p >= end_p; src_p--, dst_p-- )
+ {
+ expected = ~( RD32( dst_p ) );
+ WR32( src_p, expected );
+ }
+ for ( src_p = saddr + words - 1, dst_p = daddr + words - 1;
+ src_p >= end_p; src_p--, dst_p-- )
+ {
+ expected = ~( RD32( dst_p ) );
+ read = RD32( src_p );
+ if ( read != expected )
+ {
+ return MEMTEST_FAILURE;
+ }
+ }
+
+ return MEMTEST_SUCCESS;
+}
+
+/*---------------------------------------------------------------------------*/
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_rom/src/rom_cfe.mk b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/rom_cfe.mk
new file mode 100755
index 0000000..c45aea7
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/rom_cfe.mk
@@ -0,0 +1,370 @@
+
+#
+# CFE's version number
+#
+
+include ${TOP}/main/cfe_version.mk
+
+#
+# Default values for certain parameters
+#
+
+CFG_MLONG64 ?= 0
+CFG_LITTLE ?= 0
+CFG_RELOC ?= 0
+CFG_UNCACHED ?= 0
+CFG_NEWRELOC ?= 0
+CFG_BOOTRAM ?= 0
+CFG_VGACONSOLE ?= 0
+CFG_PCI ?= 1
+CFG_LDT_REV_017 ?= 0
+CFG_ZLIB ?= 0
+CFG_BIENDIAN ?= 0
+CFG_DOWNLOAD ?= 0
+CFG_RAMAPP ?= 0
+CFG_USB ?= 0
+
+#
+# Paths to other parts of the firmware. Everything's relative to ${TOP}
+# so that you can actually do a build anywhere you want.
+#
+
+ARCH_TOP = ${TOP}/arch/${ARCH}
+ARCH_SRC = ${ARCH_TOP}/common/src
+ARCH_INC = ${ARCH_TOP}/common/include
+CPU_SRC = ${ARCH_TOP}/cpu/${CPU}/src
+CPU_INC = ${ARCH_TOP}/cpu/${CPU}/include
+#
+# It's actually optional to have a 'board'
+# directory. If you don't specify BOARD,
+# don't include the files.
+#
+
+ifneq ("$(strip ${BOARD})","")
+BOARD_SRC = ${ARCH_TOP}/board/${BOARD}/src
+BOARD_INC = ${ARCH_TOP}/board/${BOARD}/include
+endif
+
+#
+# Preprocessor defines for CFE's version number
+#
+
+VDEF = -DCFE_VER_MAJ=${CFE_VER_MAJ} -DCFE_VER_MIN=${CFE_VER_MIN} -DCFE_VER_ECO=${CFE_VER_ECO}
+
+#
+# Construct the list of paths that will eventually become the include
+# paths and VPATH
+#
+
+SRCDIRS = ${ARCH_SRC} ${CPU_SRC} ${BOARD_SRC} ${TOP}/main ${TOP}/vendor ${TOP}/include ${TOP}/net ${TOP}/dev ${TOP}/pci ${TOP}/ui ${TOP}/lib ${TOP}/common ${TOP}/verif ${TOP}/lzma
+
+CFE_INC = ${TOP}/include ${TOP}/pci ${TOP}/net
+
+ifeq ($(strip ${CFG_VGACONSOLE}),1)
+SRCDIRS += ${TOP}/x86emu ${TOP}/pccons
+CFE_INC += ${TOP}/x86emu ${TOP}/pccons
+endif
+
+ifeq ($(strip ${CFG_VAPI}),1)
+SRCDIRS += ${TOP}/verif
+CFE_INC += ${TOP}/verif
+endif
+
+ifeq ($(strip ${CFG_ZLIB}),1)
+SRCDIRS += ${TOP}/zlib
+CFE_INC += ${TOP}/zlib
+endif
+
+
+INCDIRS = $(patsubst %,-I%,$(subst :, ,$(ARCH_INC) $(CPU_INC) $(BOARD_INC) $(CFE_INC)))
+
+VPATH = $(SRCDIRS)
+
+#
+# Bi-endian support: If we're building the little-endian
+# version, use a different linker script so we can locate the
+# ROM at a higher address. You'd think we could do this with
+# normal linker command line switches, but there appears to be no
+# command-line way to override the 'AT' qualifier in the linker script.
+#
+
+CFG_TEXTAT1MB=0
+ifeq ($(strip ${CFG_BIENDIAN}),1)
+ ifeq ($(strip ${CFG_LITTLE}),1)
+ CFG_TEXTAT1MB=1
+ endif
+endif
+
+
+#
+# Configure tools and basic tools flags. This include sets up
+# macros for calling the C compiler, basic flags,
+# and linker scripts.
+#
+
+include ${ARCH_SRC}/tools.mk
+
+#
+# Add some common flags that are used on any architecture.
+#
+
+CFLAGS += -I. $(INCDIRS)
+CFLAGS += -D_CFE_ ${VDEF} -DCFG_BOARDNAME=\"${CFG_BOARDNAME}\"
+
+#
+# Gross - allow more options to be supplied from command line
+#
+
+ifdef CFG_OPTIONS
+OPTFLAGS = $(patsubst %,-D%,$(subst :, ,$(CFG_OPTIONS)))
+CFLAGS += ${OPTFLAGS}
+endif
+
+ifeq ($(strip $(BRCM_IKOS)),y)
+CFLAGS += -DCONFIG_BRCM_IKOS
+endif
+
+#
+# Add flash driver support.
+#
+
+ifeq ($(strip $(BLD_NAND)),1)
+# BUILD NAND flash boot loader
+ifeq ($(strip $(BRCM_CHIP)),6328)
+INC_CFI_FLASH_DRIVER=0
+INC_SPI_FLASH_DRIVER=0
+INC_NAND_FLASH_DRIVER=1
+endif
+ifeq ($(strip $(BRCM_CHIP)),6362)
+INC_CFI_FLASH_DRIVER=0
+INC_SPI_FLASH_DRIVER=0
+INC_NAND_FLASH_DRIVER=1
+endif
+ifeq ($(strip $(BRCM_CHIP)),6368)
+INC_CFI_FLASH_DRIVER=0
+INC_SPI_FLASH_DRIVER=0
+INC_NAND_FLASH_DRIVER=1
+endif
+ifeq ($(strip $(BRCM_CHIP)),6816)
+INC_CFI_FLASH_DRIVER=0
+INC_SPI_FLASH_DRIVER=0
+INC_NAND_FLASH_DRIVER=1
+endif
+
+else
+# BUILD NOR flash boot loader
+ifeq ($(strip $(BRCM_CHIP)),6328)
+INC_CFI_FLASH_DRIVER=0
+INC_SPI_FLASH_DRIVER=1
+INC_NAND_FLASH_DRIVER=0
+endif
+ifeq ($(strip $(BRCM_CHIP)),6362)
+INC_CFI_FLASH_DRIVER=0
+INC_SPI_FLASH_DRIVER=1
+INC_NAND_FLASH_DRIVER=0
+endif
+ifeq ($(strip $(BRCM_CHIP)),6368)
+INC_CFI_FLASH_DRIVER=1
+INC_SPI_FLASH_DRIVER=1
+INC_NAND_FLASH_DRIVER=0
+endif
+ifeq ($(strip $(BRCM_CHIP)),6816)
+INC_CFI_FLASH_DRIVER=1
+INC_SPI_FLASH_DRIVER=1
+INC_NAND_FLASH_DRIVER=0
+endif
+endif
+
+ifeq ($(strip $(BLD_SPI_NAND)),1)
+INC_CFI_FLASH_DRIVER=0
+INC_SPI_FLASH_DRIVER=1
+INC_NAND_FLASH_DRIVER=0
+INC_SPI_PROG_NAND=1
+else
+INC_SPI_PROG_NAND=0
+endif
+
+CFLAGS += -DINC_CFI_FLASH_DRIVER=$(INC_CFI_FLASH_DRIVER)
+CFLAGS += -DINC_SPI_FLASH_DRIVER=$(INC_SPI_FLASH_DRIVER)
+CFLAGS += -DINC_NAND_FLASH_DRIVER=$(INC_NAND_FLASH_DRIVER)
+CFLAGS += -DINC_SPI_PROG_NAND=$(INC_SPI_PROG_NAND)
+
+#
+# This is the makefile's main target. Note that we actually
+# do most of the work in 'ALL' not 'all', since we include
+# other makefiles after this point.
+#
+
+all : build_date.c ALL
+
+#
+# Macros that expand to the list of arch-independent files
+#
+
+LZMAOBJS = LzmaDecode.o dcapi.o
+DEVOBJS = lib_malloc.o
+## dev_newflash.o dev_null.o dev_promice.o dev_ide_common.o dev_ns16550.o dev_ds17887clock.o dev_flash.o
+
+##lib_hssubr.o lib_physio.o lib_printf.o lib_misc.o \ lib_arena.o lib_queue.o
+## lib_qsort.o lib_string.o lib_string2.o
+
+NETOBJS =
+## net_tcp.o net_tcpbuf.o dev_tcpconsole.o net_dhcp.o net_icmp.o net_ether.o net_tftp.o net_ip.o net_udp.o net_dns.o net_arp.o net_api.o
+
+CFEOBJS =
+## cfe_iocb_dispatch.o cfe_devfuncs.o \ cfe_console.o cfe_timer.o cfe_attach.o cfe_background.o cfe_zlibfs.o
+## cfe_mem.o
+## cfe_error.o build_date.o \
+## cfe_rawfs.o cfe_xreq.o cfe_filesys.o
+## cfe_fatfs.o cfe_httpfs.o cfe_ldr_srec.o cfe_autoboot.o cfe_boot.o cfe_ldr_elf.o cfe_ldr_raw.o cfe_loader.o
+## cfe_main.o nvram_subr.o url.o cfe_savedata.o env_subr.o
+UIOBJS =
+##ui_command.o ui_cmddisp.o
+## ui_pcicmds.o \ui_tcpcmds.o ui_memcmds.o ui_loadcmds.o ui_flash.o ui_netcmds.o ui_envcmds.o ui_devcmds.o
+## ui_examcmds.o ui_misccmds.o \
+## ui_test_disk.o ui_test_ether.o ui_test_flash.o ui_test_uart.o
+
+#
+# Add more object files if we're supporting PCI
+#
+
+ifeq ($(strip ${CFG_PCI}),1)
+PCIOBJS = pciconf.o ldtinit.o pci_subr.o
+PCIOBJS += pci_devs.o
+DEVOBJS += dev_sp1011.o dev_ht7520.o
+DEVOBJS += dev_ide_pci.o dev_ns16550_pci.o
+DEVOBJS += dev_tulip.o dev_dp83815.o
+CFLAGS += -DCFG_PCI=1
+ifeq ($(strip ${CFG_LDT_REV_017}),1)
+CFLAGS += -DCFG_LDT_REV_017=1
+endif
+ifeq ($(strip ${CFG_DOWNLOAD}),1)
+DEVOBJS += dev_bcm1250.o download.data
+CFLAGS += -DCFG_DOWNLOAD=1
+endif
+endif
+
+#
+# If doing bi-endian, add the compiler switch to change
+# the way the vectors are generated. These switches are
+# only added to the big-endian portion of the ROM,
+# which is located at the real boot vector.
+#
+
+ifeq ($(strip ${CFG_BIENDIAN}),1)
+ ifeq ($(strip ${CFG_LITTLE}),0)
+ CFLAGS += -DCFG_BIENDIAN=1
+ endif
+endif
+
+#
+# Include the makefiles for the architecture-common, cpu-specific,
+# and board-specific directories. Each of these will supply
+# some files to "ALLOBJS". The BOARD directory is optional
+# as some ports are so simple they don't need boad-specific stuff.
+#
+
+include ${ARCH_SRC}/Makefile
+include ${CPU_SRC}/Makefile
+
+ifneq ("$(strip ${BOARD})","")
+include ${BOARD_SRC}/Makefile
+endif
+
+#
+# Add the common object files here.
+#
+
+ALLOBJS += $(LIBOBJS) $(DEVOBJS) $(CFEOBJS) $(VENOBJS) $(UIOBJS) $(NETOBJS)
+#$(PCIOBJS)
+
+#
+# VAPI continues to be a special case.
+#
+
+ifeq ($(strip ${CFG_VAPI}),1)
+include ${TOP}/verif/Makefile
+endif
+
+#
+# USB support
+#
+
+ifeq ($(strip ${CFG_USB}),1)
+SRCDIRS += ${TOP}/usb
+CFE_INC += ${TOP}/usb
+include ${TOP}/usb/Makefile
+endif
+
+#
+# If we're doing the VGA console thing, pull in the x86 emulator
+# and the pcconsole subsystem
+#
+
+ifeq ($(strip ${CFG_VGACONSOLE}),1)
+include ${TOP}/x86emu/Makefile
+include ${TOP}/pccons/Makefile
+endif
+
+#
+# If we're including ZLIB, then add its makefile.
+#
+
+##ifeq ($(strip ${CFG_ZLIB}),1)
+##include ${TOP}/zlib/Makefile
+CFLAGS += -DCFG_ZLIB=1 -DMY_ZCALLOC -DNO_MEMCPY
+##endif
+
+.PHONY : all
+.PHONY : ALL
+.PHONY : build_date.c
+
+#
+# Build the local tools that we use to construct other source files
+#
+
+mkpcidb : ${TOP}/hosttools/mkpcidb.c
+ gcc -o mkpcidb ${TOP}/hosttools/mkpcidb.c
+
+memconfig : ${TOP}/hosttools/memconfig.c
+ gcc -o memconfig -D_MCSTANDALONE_ -D_MCSTANDALONE_NOISY_ -I${TOP}/arch/mips/cpu/sb1250/include ${TOP}/hosttools/memconfig.c ${TOP}/arch/${ARCH}/cpu/${CPU}/src/sb1250_draminit.c
+
+pcidevs_data2.h : mkpcidb ${TOP}/pci/pcidevs_data.h
+ ./mkpcidb > pcidevs_data2.h
+
+mkflashimage : ${TOP}/hosttools/mkflashimage.c
+ gcc -o mkflashimage -I${TOP}/include ${TOP}/hosttools/mkflashimage.c
+
+pci_subr.o : ${TOP}/pci/pci_subr.c pcidevs_data2.h
+
+##build_date.c :
+## echo "const char *builddate = \"`date`\";" > build_date.c
+## echo "const char *builduser = \"`whoami`@`hostname`\";" >> build_date.c
+
+#
+# Make a define for the board name
+#
+
+CFLAGS += -D_$(patsubst "%",%,${CFG_BOARDNAME})_
+
+LIBCFE = libcfe.a
+
+%.o : %.c
+ $(GCC) $(CFLAGS) -o $@ $<
+
+%.o : %.S
+ $(GCC) $(CFLAGS) -o $@ $<
+
+#
+# This rule constructs "libcfe.a" which contains most of the object
+# files.
+#
+
+$(LIBCFE) : $(ALLOBJS)
+ rm -f $(LIBCFE)
+ $(AR) cr $(LIBCFE) $(ALLOBJS)
+ $(RANLIB) $(LIBCFE)
+
+
+
+
diff --git a/cfe/cfe/arch/mips/common/include/addrspace.h b/cfe/cfe/arch/mips/common/include/addrspace.h
new file mode 100644
index 0000000..6330851
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/include/addrspace.h
@@ -0,0 +1,63 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Address space macros File: addrspace.h
+ *
+ * Macros to deal with physical, virtual, and uncached addresses.
+ * for MIPS, these map to the appropriate KSEG0/KSEG1 macros
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "sbmips.h"
+
+#define PHYSADDR(x) K0_TO_PHYS(x)
+
+/* If running uncached, force all kernel addresses to be uncached */
+#if CFG_RUNFROMKSEG0
+#define KERNADDR(x) PHYS_TO_K0(x)
+#else
+#define KERNADDR(x) PHYS_TO_K1(x)
+#endif
+
+#define UNCADDR(x) PHYS_TO_K1(x)
+
+
+
diff --git a/cfe/cfe/arch/mips/common/include/disasm.h b/cfe/cfe/arch/mips/common/include/disasm.h
new file mode 100644
index 0000000..8a8e7b7
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/include/disasm.h
@@ -0,0 +1,61 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * MIPS disassembler File: disasm.h
+ *
+ * MIPS disassembler (used by ui_examcmds.c)
+ *
+ * Author: Justin Carlson (carlson@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifndef DISASM_H
+#define DISASM_H
+
+/* Returns a pointer to a read-only string containing the intstruction name */
+char *disasm_inst_name(uint32_t inst);
+
+/* Copies a disassembled version of the instruction into buf, null terminating the
+string. Will not exceed buf_size bytes written; if the disassembled string is
+longer than buf_size, buf_size-1 bytes of the string will be written and that string
+will be null-terminated */
+void disasm_inst(char *buf, int buf_size, uint32_t inst, uint64_t pc);
+#endif
+
+
+
diff --git a/cfe/cfe/arch/mips/common/include/exception.h b/cfe/cfe/arch/mips/common/include/exception.h
new file mode 100644
index 0000000..70e87c2
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/include/exception.h
@@ -0,0 +1,223 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Exception/trap handler defs File: exception.h
+ *
+ * This module describes the exception handlers, exception
+ * trap frames, and dispatch.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifdef __ASSEMBLER__
+#define _XAIDX(x) (8*(x))
+#else
+#define _XAIDX(x) (x)
+#endif
+
+
+/* *********************************************************************
+ * Exception vectors from the MIPS specification
+ ********************************************************************* */
+
+#define MIPS_ROM_VEC_RESET 0x0000
+#define MIPS_ROM_VEC_TLBFILL 0x0200
+#define MIPS_ROM_VEC_XTLBFILL 0x0280
+#define MIPS_ROM_VEC_CACHEERR 0x0300
+#define MIPS_ROM_VEC_EXCEPTION 0x0380
+#define MIPS_ROM_VEC_INTERRUPT 0x0400
+#define MIPS_ROM_VEC_EJTAG 0x0480
+
+#define MIPS_RAM_VEC_TLBFILL 0x0000
+#define MIPS_RAM_VEC_XTLBFILL 0x0080
+#define MIPS_RAM_VEC_EXCEPTION 0x0180
+#define MIPS_RAM_VEC_INTERRUPT 0x0200
+#define MIPS_RAM_VEC_CACHEERR 0x0100
+#define MIPS_RAM_VEC_END 0x0300
+
+#define MIPS_RAM_EXL_VEC_TLBFILL 0x0100
+#define MIPS_RAM_EXL_VEC_XTLBFILL 0x0180
+
+
+/* *********************************************************************
+ * Fixed locations of other low-memory objects. We stuff some
+ * important data in the spaces between the vectors.
+ ********************************************************************* */
+
+#define CFE_LOCORE_GLOBAL_GP 0x0040 /* our "handle" */
+#define CFE_LOCORE_GLOBAL_SP 0x0048 /* Stack pointer for exceptions */
+#define CFE_LOCORE_GLOBAL_K0TMP 0x0050 /* Used by cache error handler */
+#define CFE_LOCORE_GLOBAL_K1TMP 0x0058 /* Used by cache error handler */
+#define CFE_LOCORE_GLOBAL_RATMP 0x0060 /* Used by cache error handler */
+#define CFE_LOCORE_GLOBAL_GPTMP 0x0068 /* Used by cache error handler */
+#define CFE_LOCORE_GLOBAL_CERRH 0x0070 /* Pointer to cache error handler */
+
+#define CFE_LOCORE_GLOBAL_T0TMP 0x0240 /* used by cache error handler */
+#define CFE_LOCORE_GLOBAL_T1TMP 0x0248 /* used by cache error handler */
+#define CFE_LOCORE_GLOBAL_T2TMP 0x0250 /* used by cache error handler */
+#define CFE_LOCORE_GLOBAL_T3TMP 0x0258 /* used by cache error handler */
+
+/* *********************************************************************
+ * Offsets into our exception handler table.
+ ********************************************************************* */
+
+#define XTYPE_RESET 0
+#define XTYPE_TLBFILL 8
+#define XTYPE_XTLBFILL 16
+#define XTYPE_CACHEERR 24
+#define XTYPE_EXCEPTION 32
+#define XTYPE_INTERRUPT 40
+#define XTYPE_EJTAG 48
+
+/* *********************************************************************
+ * Exception frame definitions.
+ ********************************************************************* */
+
+/*
+ * The exception frame is divided up into pieces, representing the different
+ * parts of the processor that the data comes from:
+ *
+ * CP0: Words 0..7
+ * Int Regs: Words 8..41
+ * FP Regs: Words 42..73
+ * Total size: 74 words
+ */
+
+#define EXCEPTION_SIZE _XAIDX(74)
+
+#define XCP0_BASE 0
+#define XGR_BASE 8
+#define XFR_BASE 42
+
+#define _XCP0IDX(x) _XAIDX((x)+XCP0_BASE)
+#define XCP0_SR _XCP0IDX(0)
+#define XCP0_CAUSE _XCP0IDX(1)
+#define XCP0_EPC _XCP0IDX(2)
+#define XCP0_VADDR _XCP0IDX(3)
+#define XCP0_PRID _XCP0IDX(4)
+
+#define _XGRIDX(x) _XAIDX((x)+XGR_BASE)
+#define XGR_ZERO _XGRIDX(0)
+#define XGR_AT _XGRIDX(1)
+#define XGR_V0 _XGRIDX(2)
+#define XGR_V1 _XGRIDX(3)
+#define XGR_A0 _XGRIDX(4)
+#define XGR_A1 _XGRIDX(5)
+#define XGR_A2 _XGRIDX(6)
+#define XGR_A3 _XGRIDX(7)
+#define XGR_T0 _XGRIDX(8)
+#define XGR_T1 _XGRIDX(9)
+#define XGR_T2 _XGRIDX(10)
+#define XGR_T3 _XGRIDX(11)
+#define XGR_T4 _XGRIDX(12)
+#define XGR_T5 _XGRIDX(13)
+#define XGR_T6 _XGRIDX(14)
+#define XGR_T7 _XGRIDX(15)
+#define XGR_S0 _XGRIDX(16)
+#define XGR_S1 _XGRIDX(17)
+#define XGR_S2 _XGRIDX(18)
+#define XGR_S3 _XGRIDX(19)
+#define XGR_S4 _XGRIDX(20)
+#define XGR_S5 _XGRIDX(21)
+#define XGR_S6 _XGRIDX(22)
+#define XGR_S7 _XGRIDX(23)
+#define XGR_T8 _XGRIDX(24)
+#define XGR_T9 _XGRIDX(25)
+#define XGR_K0 _XGRIDX(26)
+#define XGR_K1 _XGRIDX(27)
+#define XGR_GP _XGRIDX(28)
+#define XGR_SP _XGRIDX(29)
+#define XGR_FP _XGRIDX(30)
+#define XGR_RA _XGRIDX(31)
+#define XGR_LO _XGRIDX(32)
+#define XGR_HI _XGRIDX(33)
+
+
+#define _XFRIDX(x) _XAIDX((x)+XFR_BASE)
+#define XR_F0 _XFRIDX(0)
+#define XR_F1 _XFRIDX(1)
+#define XR_F2 _XFRIDX(2)
+#define XR_F3 _XFRIDX(3)
+#define XR_F4 _XFRIDX(4)
+#define XR_F5 _XFRIDX(5)
+#define XR_F6 _XFRIDX(6)
+#define XR_F7 _XFRIDX(7)
+#define XR_F8 _XFRIDX(8)
+#define XR_F9 _XFRIDX(9)
+#define XR_F10 _XFRIDX(10)
+#define XR_F11 _XFRIDX(11)
+#define XR_F12 _XFRIDX(12)
+#define XR_F13 _XFRIDX(13)
+#define XR_F14 _XFRIDX(14)
+#define XR_F15 _XFRIDX(15)
+#define XR_F16 _XFRIDX(16)
+#define XR_F17 _XFRIDX(17)
+#define XR_F18 _XFRIDX(18)
+#define XR_F19 _XFRIDX(19)
+#define XR_F20 _XFRIDX(20)
+#define XR_F21 _XFRIDX(21)
+#define XR_F22 _XFRIDX(22)
+#define XR_F23 _XFRIDX(23)
+#define XR_F24 _XFRIDX(24)
+#define XR_F25 _XFRIDX(25)
+#define XR_F26 _XFRIDX(26)
+#define XR_F27 _XFRIDX(27)
+#define XR_F28 _XFRIDX(28)
+#define XR_F29 _XFRIDX(29)
+#define XR_F30 _XFRIDX(30)
+#define XR_F31 _XFRIDX(31)
+#define XR_FCR _XFRIDX(32)
+#define XR_FID _XFRIDX(33)
+
+
+#ifndef __ASSEMBLER__
+extern void _exc_setvector(int vectype, void *vecaddr);
+extern void _exc_crash_sim(void);
+extern void _exc_cache_crash_sim(void);
+extern void _exc_restart(void);
+extern void _exc_clear_sr_exl(void);
+extern void _exc_clear_sr_erl(void);
+void cfe_exception(int code,uint64_t *info);
+void cfe_setup_exceptions(void);
+#endif
+
+
+
+
+
diff --git a/cfe/cfe/arch/mips/common/include/exchandler.h b/cfe/cfe/arch/mips/common/include/exchandler.h
new file mode 100644
index 0000000..af268f1
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/include/exchandler.h
@@ -0,0 +1,85 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Exception Handler definitions File: exchandler.h
+ *
+ * Exception handler functions and constants
+ *
+ * Author: Binh Vo (binh@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#ifndef _LIB_SETJMP_H
+#include "lib_setjmp.h"
+#endif
+
+#ifndef _LIB_QUEUE_H
+#include "lib_queue.h"
+#endif
+
+#define MEM_BYTE 1
+#define MEM_HALFWORD 2
+#define MEM_WORD 3
+#define MEM_QUADWORD 4
+
+#define EXC_NORMAL_RETURN 0
+#define EXC_CHAIN_EXC 1
+
+typedef struct jmpbuf_s {
+ queue_t stack;
+ jmp_buf jmpbuf;
+} jmpbuf_t;
+
+typedef struct exc_handler_s {
+ int catch_exc;
+ int chain_exc;
+ queue_t jmpbuf_stack;
+} exc_handler_t;
+
+extern exc_handler_t exc_handler;
+
+jmpbuf_t *exc_initialize_block(void);
+void exc_cleanup_block(jmpbuf_t *);
+void exc_cleanup_handler(jmpbuf_t *, int);
+void exc_longjmp_handler(void);
+int mem_peek(void*, long, int);
+int mem_poke(long, uint64_t, int);
+
+
+#define exc_try(jb) (lib_setjmp(((jb)->jmpbuf)))
diff --git a/cfe/cfe/arch/mips/common/include/initdata.h b/cfe/cfe/arch/mips/common/include/initdata.h
new file mode 100644
index 0000000..c5fc0d8
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/include/initdata.h
@@ -0,0 +1,68 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Data stored in initialization module File: initdata.h
+ *
+ * This file contains data declared by the init module. It also
+ * contains externs for that data so we can keep the types straight.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#if defined(__ASSEMBLER__)
+#define DECLARE_INITVAR(x) \
+ .globl x ; \
+x: _LONG_ 0
+#else
+#define DECLARE_INITVAR(x) \
+ extern long x;
+#endif
+
+DECLARE_INITVAR(mem_textreloc)
+DECLARE_INITVAR(mem_textbase)
+DECLARE_INITVAR(mem_textsize)
+DECLARE_INITVAR(mem_totalsize)
+DECLARE_INITVAR(mem_topofmem)
+DECLARE_INITVAR(mem_heapstart)
+DECLARE_INITVAR(mem_bottomofmem)
+DECLARE_INITVAR(mem_datareloc)
+DECLARE_INITVAR(cpu_prid)
+
+
diff --git a/cfe/cfe/arch/mips/common/include/lib_hssubr.h b/cfe/cfe/arch/mips/common/include/lib_hssubr.h
new file mode 100644
index 0000000..b4df439
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/include/lib_hssubr.h
@@ -0,0 +1,84 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * "Hyperspace" access routines File: lib_hssubr.h
+ *
+ * Constants, macros, and definitions for routines to deal with
+ * hyperspace (beyond 256MB) on MIPS processors.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#ifndef _LIB_HSSUBR_H
+#define _LIB_HSSUBR_H
+
+/*
+ * If __long64 we can do this via macros. Otherwise, call
+ * the magic functions.
+ */
+
+#if __long64
+
+typedef long hsaddr_t;
+
+#define hs_write8(a,b) *((volatile uint8_t *) (a)) = (b)
+#define hs_write16(a,b) *((volatile uint16_t *) (a)) = (b)
+#define hs_write32(a,b) *((volatile uint32_t *) (a)) = (b)
+#define hs_write64(a,b) *((volatile uint32_t *) (a)) = (b)
+#define hs_read8(a) *((volatile uint8_t *) (a))
+#define hs_read16(a) *((volatile uint16_t *) (a))
+#define hs_read32(a) *((volatile uint32_t *) (a))
+#define hs_read64(a) *((volatile uint64_t *) (a))
+
+#else /* not __long64 */
+
+typedef long long hsaddr_t;
+
+extern void hs_write8(hsaddr_t a,uint8_t b);
+extern void hs_write16(hsaddr_t a,uint16_t b);
+extern void hs_write32(hsaddr_t a,uint32_t b);
+extern void hs_write64(hsaddr_t a,uint64_t b);
+extern uint8_t hs_read8(hsaddr_t a);
+extern uint16_t hs_read16(hsaddr_t a);
+extern uint32_t hs_read32(hsaddr_t a);
+extern uint64_t hs_read64(hsaddr_t a);
+#endif
+
+#endif
diff --git a/cfe/cfe/arch/mips/common/include/lib_physio.h b/cfe/cfe/arch/mips/common/include/lib_physio.h
new file mode 100644
index 0000000..00d0093
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/include/lib_physio.h
@@ -0,0 +1,100 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Physical memory peek/poke routines File: lib_physio.h
+ *
+ * Little stub routines to allow access to arbitrary physical
+ * addresses. In most cases this should not be needed, as
+ * many physical addresses are within kseg1, but this handles
+ * the cases that are not automagically, so we don't need
+ * to mess up the code with icky macros and such.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#ifndef _LIB_PHYSIO_H
+#define _LIB_PHYSIO_H
+
+//#ifndef _SB_MIPS_H
+//#include "sbmips.h"
+//#endif
+
+/*
+ * If __long64 we can do this via macros. Otherwise, call
+ * the magic functions.
+ */
+
+#if __long64
+
+typedef long physaddr_t;
+#define _PHYSADDR_T_DEFINED_
+
+/*#define __UNCADDRX(x) PHYS_TO_XKSEG_UNCACHED(x)*/
+#define __UNCADDRX(x) (((physaddr_t)(x))|0x9000000000000000)
+
+
+#define phys_write8(a,b) *((volatile uint8_t *) __UNCADDRX(a)) = (b)
+#define phys_write16(a,b) *((volatile uint16_t *) __UNCADDRX(a)) = (b)
+#define phys_write32(a,b) *((volatile uint32_t *) __UNCADDRX(a)) = (b)
+#define phys_write64(a,b) *((volatile uint64_t *) __UNCADDRX(a)) = (b)
+#define phys_read8(a) *((volatile uint8_t *) __UNCADDRX(a))
+#define phys_read16(a) *((volatile uint16_t *) __UNCADDRX(a))
+#define phys_read32(a) *((volatile uint32_t *) __UNCADDRX(a))
+#define phys_read64(a) *((volatile uint64_t *) __UNCADDRX(a))
+
+#else /* not __long64 */
+
+#ifdef _MIPSREGS32_
+typedef long physaddr_t; /* 32-bit-only processors can't have >32bit pa's */
+#else
+typedef long long physaddr_t; /* Otherwise, they might. */
+#endif
+
+extern void phys_write8(physaddr_t a,uint8_t b);
+extern void phys_write16(physaddr_t a,uint16_t b);
+extern void phys_write32(physaddr_t a,uint32_t b);
+extern void phys_write64(physaddr_t a,uint64_t b);
+extern uint8_t phys_read8(physaddr_t a);
+extern uint16_t phys_read16(physaddr_t a);
+extern uint32_t phys_read32(physaddr_t a);
+extern uint64_t phys_read64(physaddr_t a);
+#endif
+
+#endif
diff --git a/cfe/cfe/arch/mips/common/include/lib_setjmp.h b/cfe/cfe/arch/mips/common/include/lib_setjmp.h
new file mode 100644
index 0000000..b673222
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/include/lib_setjmp.h
@@ -0,0 +1,81 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * setjmp/longjmp defs File: lib_setjmp.h
+ *
+ * Description of the jmp_buf structure for setjmp and longjmp
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+/*
+ * Note that while lib_setjmp() and lib_longjmp() behave like setjmp()
+ * and longjmp() normally do, gcc 3.1.x (and later) assumes things about
+ * how setjmp() and longjmp() should work (even with -fno-builtins). We
+ * don't want it to do those, so these functions must be named differently.
+ */
+
+#ifdef __ASSEMBLER__
+#define _JBIDX(x) (8*(x))
+#else
+#define _JBIDX(x) (x)
+#endif
+
+
+#define JMPB_S0 _JBIDX(0)
+#define JMPB_S1 _JBIDX(1)
+#define JMPB_S2 _JBIDX(2)
+#define JMPB_S3 _JBIDX(3)
+#define JMPB_S4 _JBIDX(4)
+#define JMPB_S5 _JBIDX(5)
+#define JMPB_S6 _JBIDX(6)
+#define JMPB_S7 _JBIDX(7)
+#define JMPB_FP _JBIDX(8)
+#define JMPB_SP _JBIDX(9)
+#define JMPB_RA _JBIDX(10)
+
+#define JMPB_SIZE _JBIDX(11)
+
+#ifndef __ASSEMBLER__
+typedef long long jmp_buf[JMPB_SIZE];
+extern int lib_setjmp(jmp_buf);
+extern void lib_longjmp(jmp_buf,int val);
+#endif
+
diff --git a/cfe/cfe/arch/mips/common/include/mipsmacros.h b/cfe/cfe/arch/mips/common/include/mipsmacros.h
new file mode 100755
index 0000000..072a5e6
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/include/mipsmacros.h
@@ -0,0 +1,376 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * MIPS Macros File: mipsmacros.h
+ *
+ * Macros to deal with various mips-related things.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+/* *********************************************************************
+ * 32/64-bit macros
+ ********************************************************************* */
+
+#ifdef __long64
+#define _VECT_ .dword
+#define _LONG_ .dword
+#define SR sd
+#define LR ld
+#define ADD dadd
+#define SUB dsub
+#define MFC0 dmfc0
+#define MTC0 dmtc0
+#define REGSIZE 8
+#define BPWSIZE 3 /* bits per word size */
+#define _TBLIDX(x) ((x)*REGSIZE)
+#else
+#define _VECT_ .word
+#define _LONG_ .word
+#define SR sw
+#define LR lw
+#define ADD add
+#define SUB sub
+#define MFC0 mfc0
+#define MTC0 mtc0
+#define REGSIZE 4
+#define BPWSIZE 2
+#define _TBLIDX(x) ((x)*REGSIZE)
+#endif
+
+
+/* *********************************************************************
+ * NORMAL_VECTOR(addr,vecname,vecdest)
+ * NORMAL_XVECTOR(addr,vecname,vecdest,code)
+ *
+ * Declare a trap or dispatch vector. There are two flavors,
+ * DECLARE_XVECTOR sets up an indentifying code in k0 before
+ * jumping to the dispatch routine.
+ *
+ * Input parameters:
+ * addr - vector address
+ * vecname - for label at that address
+ * vecdest - destination (place vector jumps to)
+ * code - code to place in k0 before jumping
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+#define NORMAL_VECTOR(addr,vecname,vecdest) \
+ .globl vecname ; \
+ .org addr ; \
+vecname: b vecdest ; \
+ nop;
+
+#define NORMAL_XVECTOR(addr,vecname,vecdest,code) \
+ .globl vecname ; \
+ .org addr ; \
+vecname: b vecdest ; \
+ li k0,code ; \
+ nop;
+
+
+/* *********************************************************************
+ * Evil macros for bi-endian support.
+ *
+ * The magic here is in the instruction encoded as 0x10000014.
+ *
+ * This instruction in big-endian is: "b .+0x54"
+ * this instruction in little-endian is: "bne zero,zero,.+0x44"
+ *
+ * So, depending on what the system endianness is, it will either
+ * branch to .+0x54 or not branch at all.
+ *
+ * the instructions that follow are:
+ *
+ * 0x10000014 "magic branch" (either-endian)
+ * 0x00000000 nop (bds) (either-endian)
+ * 0xD0BF1A3C lui k0,0xBFD0 (little-endian)
+ * 0xxxxx5A27 addu k0,vector (little-endian)
+ * 0x08004003 jr k0 (little-endian)
+ * 0x00000000 nop (bds) (little-endian)
+ * ... space up to offset 0x54
+ * ......... b vecaddr (big-endian)
+ *
+ * The idea is that the big-endian firmware is first, from 0..1MB
+ * in the flash, and the little-endian firmware is second,
+ * from 1..2MB in the flash. The little-endian firmware is
+ * set to load at BFD00000, so that its initial routines will
+ * work until relocation is completed.
+ *
+ * the instructions at the vectors will either jump to the
+ * big-endian or little-endian code based on system endianness.
+ *
+ * The ROM is built by compiling CFE twice, first with
+ * CFG_BIENDIAN=1 and CFG_LITTLE=0 (big-endian) and again
+ * with CFG_BIENDIAN=1 and CFG_LITTLE=1. The resulting
+ * cfe.bin files are located at 0xBFC00000 and 0xBFD00000
+ * for big and little-endian versions, respectively.
+ *
+ * More information about how this works can be found in the
+ * CFE Manual.
+ ********************************************************************* */
+
+#define __SWAPW(x) ((((x) & 0xFF) << 8) | (((x) & 0xFF00) >> 8))
+
+#define BIENDIAN_VECTOR(addr,vecname,vecdest) \
+ .globl vecname ; \
+ .org addr ; \
+vecname: .word 0x10000014 ; \
+ .word 0 ; \
+ .word ((__SWAPW(BIENDIAN_LE_BASE >> 16)) << 16) | 0x1A3C ; \
+ .word (0x00005A27 | (((addr) & 0xFF) << 24) | (((addr) & 0xFF00) << 8)) ; \
+ .word 0x08004003 ; \
+ .word 0 ; \
+ .org ((addr) + 0x54) ; \
+ b vecdest ; \
+ nop;
+
+#define BIENDIAN_XVECTOR(addr,vecname,vecdest,code) \
+ .globl vecname ; \
+ .org addr ; \
+vecname: .word 0x10000014 ; \
+ .word 0 ; \
+ .word ((__SWAPW(BIENDIAN_LE_BASE >> 16)) << 16) | 0x1A3C ; \
+ .word (0x00005A27 | (((addr) & 0xFF) << 24) | (((addr) & 0xFF00) << 8)) ; \
+ .word 0x08004003 ; \
+ .word 0 ; \
+ .org ((addr) + 0x54) ; \
+ b vecdest ; \
+ li k0,code ; \
+ nop;
+
+
+
+/* *********************************************************************
+ * Declare the right versions of DECLARE_VECTOR and
+ * DECLARE_XVECTOR depending on how we're building stuff.
+ * Generally, we only use the biendian version if we're building
+ * as CFG_BIENDIAN=1 and we're doing the big-endian MIPS version.
+ ********************************************************************* */
+
+#if (CFG_BIENDIAN) && defined(__MIPSEB)
+#define DECLARE_VECTOR BIENDIAN_VECTOR
+#define DECLARE_XVECTOR BIENDIAN_XVECTOR
+#else
+#define DECLARE_VECTOR NORMAL_VECTOR
+#define DECLARE_XVECTOR NORMAL_XVECTOR
+#endif
+
+
+
+/* *********************************************************************
+ * LOADREL(reg,label)
+ *
+ * Load the address of a label, but do it in a position-independent
+ * way.
+ *
+ * Input parameters:
+ * reg - register to load
+ * label - label whose address to load
+ *
+ * Return value:
+ * ra is trashed!
+ ********************************************************************* */
+
+#if (!(CFG_RAMAPP))
+#define LOADREL(reg,label) \
+ la reg, label ; \
+ la ra, 100f ; \
+ sub reg, ra ; \
+ .set push ; \
+ .set noreorder ; \
+ bal 100f ; \
+ nop ; \
+ .set pop ; \
+100: ; \
+ addu reg, ra
+#else
+#define LOADREL(reg,label) \
+ la reg,label
+#endif
+
+#if (CFG_RAMAPP)
+#define FIXUP(addr)
+#else
+#define FIXUP(addr) \
+ addu addr, s6
+#endif
+
+
+
+/* *********************************************************************
+ * CALLINIT_KSEG1(label,table,offset)
+ * CALLINIT_KSEG0(label,table,offset)
+ *
+ * Call an initialization routine (usually in another module).
+ * If initialization routine lives in KSEG1 it may need
+ * special fixing if using the cached version of CFE (this is
+ * the default case). CFE is linked at a KSEG0 address.
+ *
+ * Embedded PIC is especially tricky, since the "la"
+ * instruction expands to calculations involving GP.
+ * In that case, use our table of offsets to
+ * load the routine address from a table in memory.
+ *
+ * Input parameters:
+ * label - routine to call if we can call directly
+ * table - symbol name of table containing routine addresses
+ * offset - offset within the above table
+ *
+ * Return value:
+ * k1,ra is trashed.
+ ********************************************************************* */
+
+
+#if CFG_RUNFROMKSEG0
+/* Cached PIC code - call indirect through table */
+#define CALLINIT_KSEG1(table,tableoffset) \
+ LOADREL(k1,table) ; \
+ or k1,K1BASE ; \
+ LR k1,tableoffset(k1) ; \
+ FIXUP (k1); \
+ or k1,K1BASE ; \
+ jal k1
+#define CALLINIT_KSEG0(table,tableoffset) \
+ LOADREL(k1,table) ; \
+ LR k1,tableoffset(k1) ; \
+ FIXUP (k1); \
+ jal k1
+#else
+/* Uncached PIC code - call indirect through table, always same KSEG */
+#define CALLINIT_KSEG1(table,tableoffset) \
+ LOADREL(k1,table) ; \
+ LR k1,tableoffset(k1) ; \
+ FIXUP (k1); \
+ jal k1
+#define CALLINIT_KSEG0 CALLINIT_KSEG1
+#endif
+
+/*
+ * CALLINIT_RELOC is used once CFE's relocation is complete and
+ * the "mem_textreloc" variable is set up. (yes, this is nasty.)
+ * If 'gp' is set, we can presume that we've relocated
+ * and it's safe to read "mem_textreloc", otherwise use the
+ * address as-is from the table.
+ */
+
+#define CALLINIT_RELOC CALLINIT_KSEG0
+
+/* *********************************************************************
+ * SPIN_LOCK(lock,reg1,reg2)
+ *
+ * Acquire a spin lock.
+ *
+ * Input parameters:
+ * lock - symbol (address) of lock to acquire
+ * reg1,reg2 - registers we can use to acquire lock
+ *
+ * Return value:
+ * nothing (lock acquired)
+ ********************************************************************* */
+
+#define SPIN_LOCK(lock,reg1,reg2) \
+ la reg1,lock ; \
+1: sync ; \
+ ll reg2,0(reg1) ; \
+ bne reg2,zero,1b ; \
+ li reg2,1 ; \
+ sc reg2,0(reg1) ; \
+ beq reg2,zero,1b ; \
+ nop
+
+/* *********************************************************************
+ * SPIN_UNLOCK(lock,reg1)
+ *
+ * Release a spin lock.
+ *
+ * Input parameters:
+ * lock - symbol (address) of lock to release
+ * reg1 - a register we can use
+ *
+ * Return value:
+ * nothing (lock released)
+ ********************************************************************* */
+
+
+#define SPIN_UNLOCK(lock,reg1) \
+ la reg1,lock ; \
+ sw zero,0(reg1)
+
+
+/* *********************************************************************
+ * SETCCAMODE(treg,mode)
+ *
+ * Set cacheability mode. For some of the pass1 workarounds we
+ * do this alot, so here's a handy macro.
+ *
+ * Input parameters:
+ * treg - temporary register we can use
+ * mode - new mode (K_CFG_K0COH_xxx)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+#define SETCCAMODE(treg,mode) \
+ mfc0 treg,C0_CONFIG ; \
+ srl treg,treg,3 ; \
+ sll treg,treg,3 ; \
+ or treg,treg,mode ; \
+ mtc0 treg,C0_CONFIG ; \
+ HAZARD
+
+
+/* *********************************************************************
+ * Declare variables
+ ********************************************************************* */
+
+#define DECLARE_LONG(x) \
+ .global x ; \
+x: _LONG_ 0
+
+
+
+
+/*
+ * end
+ */
diff --git a/cfe/cfe/arch/mips/common/include/segtable.h b/cfe/cfe/arch/mips/common/include/segtable.h
new file mode 100755
index 0000000..8a003f0
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/include/segtable.h
@@ -0,0 +1,97 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Segment Table definitions File: segtable.h
+ *
+ * The 'segment table' (bad name) is just a list of addresses
+ * of important stuff used during initialization. We use these
+ * indirections to make life less complicated during code
+ * relocation.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#if !defined(__ASSEMBLER__)
+#define _TBLIDX(x) (x) /* C handles indexing for us */
+typedef long segtable_t; /* 32 for long32, 64 for long64 */
+#endif
+
+/*
+ * Definitions for the segment_table
+ */
+
+#define R_SEG_ETEXT _TBLIDX(0) /* end of text segment */
+#define R_SEG_FDATA _TBLIDX(1) /* Beginning of data segment */
+#define R_SEG_EDATA _TBLIDX(2) /* end of data segment */
+#define R_SEG_END _TBLIDX(3) /* End of BSS */
+#define R_SEG_FTEXT _TBLIDX(4) /* Beginning of text segment */
+#define R_SEG_FBSS _TBLIDX(5) /* Beginning of BSS */
+#define R_SEG_GP _TBLIDX(6) /* Global Pointer */
+#define R_SEG_RELOCSTART _TBLIDX(7) /* Start of reloc table */
+#define R_SEG_RELOCEND _TBLIDX(8) /* End of reloc table */
+#define R_SEG_APIENTRY _TBLIDX(9) /* API Entry address */
+
+/*
+ * Definitions for the init_table
+ */
+
+#define R_INIT_EARLYINIT _TBLIDX(0) /* pointer to board_earlyinit */
+#define R_INIT_SETLEDS _TBLIDX(1) /* pointer to board_setleds */
+#define R_INIT_DRAMINFO _TBLIDX(2) /* pointer to board_draminfo */
+#define R_INIT_CPUINIT _TBLIDX(3) /* pointer tp cpuinit */
+#define R_INIT_ALTCPU_START1 _TBLIDX(4) /* pointer to altcpu_start1 */
+#define R_INIT_ALTCPU_START2 _TBLIDX(5) /* pointer to altcpu_start2 */
+#define R_INIT_ALTCPU_RESET _TBLIDX(6) /* pointer to altcpu_reset */
+#define R_INIT_CPURESTART _TBLIDX(7) /* pointer to cpurestart */
+#define R_INIT_DRAMINIT _TBLIDX(8) /* pointer to draminit */
+#define R_INIT_CACHEOPS _TBLIDX(9) /* pointer to cacheops */
+#define R_INIT_TLBHANDLER _TBLIDX(10) /* pointer to TLB fault handler */
+#define R_INIT_CMDSTART _TBLIDX(11) /* pointer to cfe_main */
+#define R_INIT_CMDRESTART _TBLIDX(12) /* pointer to cfe_cmd_restart */
+#define R_INIT_DOXREQ _TBLIDX(13) /* pointer to cfe_doxreq */
+#define R_INIT_TP1_SWITCH _TBLIDX(14) /* pointer to tp1_switch */
+#define R_INIT_SIZERAM _TBLIDX(15) /* pointer to board_sizeram */
+
+/*
+ * Definitions for the diag_table
+ */
+
+#define R_DIAG_TEST1 _TBLIDX(0) /* after CPU and cache init, before DRAM init */
+#define R_DIAG_TEST2 _TBLIDX(1) /* after DRAM init, before main */
diff --git a/cfe/cfe/arch/mips/common/src/Makefile b/cfe/cfe/arch/mips/common/src/Makefile
new file mode 100755
index 0000000..638113d
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/Makefile
@@ -0,0 +1,38 @@
+
+#
+# This is just a Makefile fragment -- it is included by the master
+# makefile, cfe.mk
+#
+# This file should just append object file names to "ALLOBJS",
+# but since it is mean to be linked *first*, it will append
+# modules to "CRT0OBJS"
+#
+
+ifndef INIT_MIPS
+INIT_MIPS = init_mips.o
+endif
+
+ifeq ($(strip ${CFG_RAMAPP}),1)
+CRT0OBJS += init_ram.o exception.o
+else
+CRT0OBJS += $(INIT_MIPS)
+endif
+
+ifeq ($(strip ${CFG_RAMAPP}),1)
+ALLOBJS += lib_hssubr.o lib_setjmp.o mips_arena.o exchandler.o
+ALLOBJS += dev_flash_all.o dev_flashop_engine.o
+ALLOBJS += ui_memtest.o
+endif
+
+makereg : ${TOP}/hosttools/makereg.c
+ gcc -o makereg ${TOP}/hosttools/makereg.c
+
+%.inc : %.regdef makereg
+ ./makereg $< $@
+
+ui_soccmds.o : ${CPU_SRC}/ui_soccmds.c ${CPU}_socregs.inc
+
+vapi.o : ${TOP}/verif/vapi.S sb1250_socregs.inc
+
+
+
diff --git a/cfe/cfe/arch/mips/common/src/cfe_ram_cached.lds b/cfe/cfe/arch/mips/common/src/cfe_ram_cached.lds
new file mode 100644
index 0000000..4b8ce87
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/cfe_ram_cached.lds
@@ -0,0 +1,40 @@
+OUTPUT_ARCH(mips)
+ENTRY(vec_reset)
+SECTIONS
+{
+ . = 0x9fc00000; /* was 0x9fc00000 */
+ .text :
+/* AT ( 0xBFC00000 ) */ /* was 0xbfc00000 */
+ {
+ _ftext = . ;
+ *(.init)
+ eprol = .;
+ *(.text)
+ *(.fini)
+ *(.rodata)
+ _etext = .;
+ }
+
+ .data :
+ {
+ _fdata = ALIGN(16) ;
+ *(.data)
+ CONSTRUCTORS
+ . = ALIGN(16);
+ _gp = . + 0x8000;
+ *(.sdata)
+ }
+ . = ALIGN(16);
+ _edata = .;
+ _fbss = .;
+ .sbss : {
+ *(.sbss)
+ *(.scommon)
+ }
+ .bss : {
+ *(.bss)
+ *(COMMON)
+ }
+ . = ALIGN(16);
+ _end = .;
+}
diff --git a/cfe/cfe/arch/mips/common/src/cfe_ram_uncached.lds b/cfe/cfe/arch/mips/common/src/cfe_ram_uncached.lds
new file mode 100644
index 0000000..4295fe4
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/cfe_ram_uncached.lds
@@ -0,0 +1,40 @@
+OUTPUT_ARCH(mips)
+ENTRY(vec_reset)
+SECTIONS
+{
+ . = 0xbfc00000; /* was 0x9fc00000 */
+ .text :
+/* AT ( 0xBFC00000 ) */ /* was 0xbfc00000 */
+ {
+ _ftext = . ;
+ *(.init)
+ eprol = .;
+ *(.text)
+ *(.fini)
+ *(.rodata)
+ _etext = .;
+ }
+
+ .data :
+ {
+ _fdata = ALIGN(16) ;
+ *(.data)
+ CONSTRUCTORS
+ . = ALIGN(16);
+ _gp = . + 0x8000;
+ *(.sdata)
+ }
+ . = ALIGN(16);
+ _edata = .;
+ _fbss = .;
+ .sbss : {
+ *(.sbss)
+ *(.scommon)
+ }
+ .bss : {
+ *(.bss)
+ *(COMMON)
+ }
+ . = ALIGN(16);
+ _end = .;
+}
diff --git a/cfe/cfe/arch/mips/common/src/cfe_ramapp.lds b/cfe/cfe/arch/mips/common/src/cfe_ramapp.lds
new file mode 100755
index 0000000..5a7a377
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/cfe_ramapp.lds
@@ -0,0 +1,41 @@
+OUTPUT_ARCH(mips)
+ENTRY(vec_reset)
+SECTIONS
+{
+ . = 0x80601000;
+ .text :
+ {
+ _ftext = . ;
+ *(.init)
+ eprol = .;
+ *(.text)
+ *(.fini)
+ *(.rodata)
+ *(.rodata.str1.4)
+ *(.gnu.linkonce.r.*)
+ _etext = .;
+ }
+
+ .data :
+ {
+ _fdata = ALIGN(16) ;
+ *(.data)
+ CONSTRUCTORS
+ . = ALIGN(16);
+ _gp = . + 0x8000;
+ *(.sdata)
+ }
+ . = ALIGN(16);
+ _edata = .;
+ _fbss = .;
+ .sbss : {
+ *(.sbss)
+ *(.scommon)
+ }
+ .bss : {
+ *(.bss)
+ *(COMMON)
+ }
+ . = ALIGN(16);
+ _end = .;
+}
diff --git a/cfe/cfe/arch/mips/common/src/cfe_rom_cached.lds b/cfe/cfe/arch/mips/common/src/cfe_rom_cached.lds
new file mode 100755
index 0000000..2ca1353
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/cfe_rom_cached.lds
@@ -0,0 +1,40 @@
+OUTPUT_ARCH(mips)
+ENTRY(vec_reset)
+SECTIONS
+{
+ . = 0x80000000;
+ .text :
+ {
+ _ftext = . ;
+ *(.init)
+ eprol = .;
+ *(.text)
+ *(.fini)
+ *(.rodata)
+ _etext = .;
+ }
+
+ .data :
+ {
+ _fdata = ALIGN(16) ;
+ *(.data)
+ CONSTRUCTORS
+ . = ALIGN(16);
+ _gp = . + 0x8000;
+ *(.sdata)
+ }
+ . = ALIGN(16);
+ _edata = .;
+ .reginfo : {}
+ _fbss = .;
+ .sbss : {
+ *(.sbss)
+ *(.scommon)
+ }
+ .bss : {
+ *(.bss)
+ *(COMMON)
+ }
+ . = ALIGN(16);
+ _end = .;
+}
diff --git a/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached.lds b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached.lds
new file mode 100644
index 0000000..ee94831
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached.lds
@@ -0,0 +1,43 @@
+OUTPUT_ARCH(mips)
+ENTRY(vec_reset)
+SECTIONS
+{
+ . = 0x9FC00000;
+ .text :
+ AT ( 0xBFC00000 )
+ {
+ _ftext = . ;
+ *(.init)
+ eprol = .;
+ *(.text)
+ PROVIDE (__runtime_reloc_start = .);
+ *(.rel.sdata)
+ PROVIDE (__runtime_reloc_stop = .);
+ *(.fini)
+ *(.rodata)
+ _etext = .;
+ }
+ .data 0x80001000 :
+ AT ( ((ADDR(.text)|0xB0000000) + SIZEOF ( .text ) + 15) & 0xFFFFFFF0)
+ {
+ _gp = ALIGN(16) + 0x8000;
+ _fdata = .;
+ *(.rdata)
+ *(.data)
+ CONSTRUCTORS
+ *(.sdata)
+ }
+ . = ALIGN(16);
+ _edata = .;
+ _fbss = .;
+ .sbss : {
+ *(.sbss)
+ *(.scommon)
+ }
+ .bss : {
+ *(.bss)
+ *(COMMON)
+ }
+ . = ALIGN(16);
+ _end = .;
+}
diff --git a/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached_biendian.lds b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached_biendian.lds
new file mode 100644
index 0000000..78421a4
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_cached_biendian.lds
@@ -0,0 +1,49 @@
+/*
+ * This linker script is exactly the same as cfe_rom_reloc_cached.lds
+ * except our start address is at BFD00000, 1MB into the
+ * ROM. We locate the little-endian version of CFE at this address
+ * in bi-endian ROM support.
+ */
+OUTPUT_ARCH(mips)
+ENTRY(vec_reset)
+SECTIONS
+{
+ . = 0x9FD00000;
+ .text :
+ AT ( 0xBFD00000 )
+ {
+ _ftext = . ;
+ *(.init)
+ eprol = .;
+ *(.text)
+ PROVIDE (__runtime_reloc_start = .);
+ *(.rel.sdata)
+ PROVIDE (__runtime_reloc_stop = .);
+ *(.fini)
+ *(.rodata)
+ _etext = .;
+ }
+ .data 0x80001000 :
+ AT ( ((ADDR(.text)|0xB0000000) + SIZEOF ( .text ) + 15) & 0xFFFFFFF0)
+ {
+ _gp = ALIGN(16) + 0x8000;
+ _fdata = .;
+ *(.rdata)
+ *(.data)
+ CONSTRUCTORS
+ *(.sdata)
+ }
+ . = ALIGN(16);
+ _edata = .;
+ _fbss = .;
+ .sbss : {
+ *(.sbss)
+ *(.scommon)
+ }
+ .bss : {
+ *(.bss)
+ *(COMMON)
+ }
+ . = ALIGN(16);
+ _end = .;
+}
diff --git a/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_uncached.lds b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_uncached.lds
new file mode 100644
index 0000000..0c62889
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/cfe_rom_reloc_uncached.lds
@@ -0,0 +1,41 @@
+OUTPUT_ARCH(mips)
+ENTRY(vec_reset)
+SECTIONS
+{
+ . = 0xBFC00000;
+ .text : {
+ _ftext = . ;
+ *(.init)
+ eprol = .;
+ *(.text)
+ PROVIDE (__runtime_reloc_start = .);
+ *(.rel.sdata)
+ PROVIDE (__runtime_reloc_stop = .);
+ *(.fini)
+ *(.rodata)
+ _etext = .;
+ }
+ .data 0xA0001000 :
+ AT ( ((ADDR(.text)|0xB0000000) + SIZEOF ( .text ) + 15) & 0xFFFFFFF0)
+ {
+ _gp = ALIGN(16) + 0x8000;
+ _fdata = .;
+ *(.rdata)
+ *(.data)
+ CONSTRUCTORS
+ *(.sdata)
+ }
+ . = ALIGN(16);
+ _edata = .;
+ _fbss = .;
+ .sbss : {
+ *(.sbss)
+ *(.scommon)
+ }
+ .bss : {
+ *(.bss)
+ *(COMMON)
+ }
+ . = ALIGN(16);
+ _end = .;
+}
diff --git a/cfe/cfe/arch/mips/common/src/cfe_rom_uncached.lds b/cfe/cfe/arch/mips/common/src/cfe_rom_uncached.lds
new file mode 100644
index 0000000..a0362ba
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/cfe_rom_uncached.lds
@@ -0,0 +1,39 @@
+OUTPUT_ARCH(mips)
+ENTRY(vec_reset)
+SECTIONS
+{
+ . = 0xBFC00000;
+ .text : {
+ _ftext = . ;
+ *(.init)
+ eprol = .;
+ *(.text)
+ *(.fini)
+ *(.rodata)
+ _etext = .;
+ }
+
+ .data 0xA1F00000 :
+ AT ( ((ADDR(.text)|0xB0000000) + SIZEOF ( .text ) + 15) & 0xFFFFFFF0)
+ {
+ _fdata = ALIGN(16) ;
+ *(.data)
+ CONSTRUCTORS
+ . = ALIGN(16);
+ _gp = . + 0x8000;
+ *(.sdata)
+ }
+ . = ALIGN(16);
+ _edata = .;
+ _fbss = .;
+ .sbss : {
+ *(.sbss)
+ *(.scommon)
+ }
+ .bss : {
+ *(.bss)
+ *(COMMON)
+ }
+ . = ALIGN(16);
+ _end = .;
+}
diff --git a/cfe/cfe/arch/mips/common/src/dev_flash_all.S b/cfe/cfe/arch/mips/common/src/dev_flash_all.S
new file mode 100644
index 0000000..6dbb581
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/dev_flash_all.S
@@ -0,0 +1,220 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Flash "self-write" module File: flash_write_all.S
+ *
+ * This module takes care of the case of writing to the flash
+ * memory that CFE is currently reading its code from. It is
+ * assumed that you'll be doing a complete flash update,
+ * so this code erases the affected sectors, reprograms them,
+ * and jumps to the boot sector.
+ *
+ * Note: this code is written to be position-independent, even
+ * for non-PIC versions of CFE! It will be copied (with memcpy)
+ * into the heap for execution.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "sbmips.h"
+#include "dev_flash.h"
+#include "mipsmacros.h"
+
+#define WRITEFLASH(base,offset,value) \
+ li t0,value ; \
+ sb t0,offset(base)
+
+
+/* *********************************************************************
+ * flash_write_all(data,flashbase,size,secsize)
+ *
+ * Write bytes to flash, erasing affected sectors first.
+ *
+ * Input parameters:
+ * a0 - data - pointer to data to write
+ * a1 - flashbase - base (phys addr) of flash area
+ * a2 - size - number of bytes to write
+ * a3 - secsize - flash sector size
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+#define data a0
+#define flashbase a1
+#define datasize a2
+#define secsize a3
+
+#define secidx t4
+#define secptr t5
+
+LEAF(flash_write_all)
+
+ /*
+ * Mask all interrupts. An exception with BEV set would be very bad.
+ */
+
+ mfc0 v0,C0_SR # Get current interrupt flag
+ li v1,M_SR_IE # master interrupt control
+ not v1 # disable interrupts
+ and v0,v1 # SR now has IE=0
+ mtc0 v0,C0_SR # put back into CP0
+
+ /*
+ * Get KSEG1 addr of flash
+ */
+
+ or flashbase,K1BASE
+
+
+ /*
+ * Do an "unlock write" sequence (cycles 1-2)
+ */
+
+ WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+
+ /*
+ * send the erase command (cycle 3)
+ */
+
+ WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3)
+
+ /*
+ * Do an "unlock write" sequence (cycles 4-5)
+ */
+
+ WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+
+ /*
+ * Send the "erase all" qualifier (cycle 6)
+ */
+
+ WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_ALL_6)
+
+ /*
+ * Wait for the erase to complete
+ */
+
+1: lb t0,0(secptr) # get byte
+ and t0,0xFF # test hi byte
+ bne t0,0xFF,1b # go till bit is set
+
+
+ /*
+ * Okay, now loop through the bytes and write them to the
+ * flash.
+ */
+
+ move secptr,flashbase
+ move secidx,datasize
+
+proglp:
+
+ /*
+ * Do an "unlock write" sequence
+ */
+
+ WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+
+ /*
+ * Send a program command
+ */
+ WRITEFLASH(flashbase,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_PROGRAM)
+
+ /*
+ * Write a byte
+ */
+
+ lbu t0,0(data)
+ sb t0,0(secptr) # t0 = byte written to flash
+
+
+ /*
+ * Wait for write to complete
+ */
+
+1: lbu t2,0(secptr) # t2 = byte from flash
+
+ and t1,t2,0x80 # done if bit7 of flash
+ and t0,t0,0x80 # is same as bit7 of data
+ beq t1,t0,2f
+
+ and t1,t2,0x20 # not done if bit5
+ bne t1,0x20,1b # is still set
+2:
+
+ /*
+ * next byte...
+ */
+
+ add a0,1 # next source byte
+ add secptr,1 # next dest byte
+ sub datasize,1 # one less count
+ bgt datasize,0,proglp
+
+ /*
+ * All done, reboot system
+ */
+
+ li v0,0xBFC00000
+ j v0
+
+flash_write_all_end:
+ nop
+
+END(flash_write_all)
+
+/* *********************************************************************
+ * Data
+ ********************************************************************* */
+
+ .sdata
+
+ .globl flash_write_all_ptr
+ .globl flash_write_all_len
+
+flash_write_all_ptr:
+ _VECT_ flash_write_all
+flash_write_all_len:
+ .word flash_write_all_end-flash_write_all
+
+
diff --git a/cfe/cfe/arch/mips/common/src/dev_flashop_engine.S b/cfe/cfe/arch/mips/common/src/dev_flashop_engine.S
new file mode 100644
index 0000000..29ade6a
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/dev_flashop_engine.S
@@ -0,0 +1,695 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Flash "self-write" module File: dev_flashop_engine.S
+ *
+ * This module takes care of the case of writing to the flash
+ * memory that CFE is currently reading its code from.
+ *
+ * Note: this code is written to be position-independent, even
+ * for non-PIC versions of CFE! It will be copied (with memcpy)
+ * into the heap for execution.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "sbmips.h"
+#include "mipsmacros.h"
+
+#include "bsp_config.h"
+#include "dev_newflash.h"
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define FLASHCMD_8(base,offset,value) \
+ li t0,value ; \
+ sb t0,offset(base)
+
+#define FLASHCMD_16(base,offset,value) \
+ li t0,value ; \
+ sh t0,((offset)<<1)(base)
+
+#define FLASHCMD_16B(base,offset,value) \
+ li t0,value ; \
+ sb t0,((offset)<<1)(base)
+
+
+/* *********************************************************************
+ * flashop_engine
+ *
+ * This routine is written in a PIC method to allow us to do
+ * flash operations without any help from CFE. We need to do
+ * this when we're not relocated and want to muck with the
+ * flash we're running from.
+ *
+ * This routine follows some simple instructions in a table,
+ * so you can batch up the operations in one place.
+ *
+ * Input parameters:
+ * a0 - pointer to instruction list
+ *
+ * Return value:
+ * v0 - 0 if all instructions succeeded
+ * else less than zero, # of failing instructions
+ ********************************************************************* */
+
+ .text
+
+#define reg_op t3
+#define reg_base t4
+#define reg_dest t5
+#define reg_src t6
+#define reg_cnt t7
+
+LEAF(flashop_engine)
+
+instloop: LR reg_op,FEINST_OP(a0) /* Load instruction */
+ LR reg_base,FEINST_BASE(a0)
+ LR reg_dest,FEINST_DEST(a0)
+ LR reg_src,FEINST_SRC(a0)
+ LR reg_cnt,FEINST_CNT(a0)
+ li v0,0 /* total of result values */
+ li v1,0 /* result for this function */
+
+#ifdef __long64
+ dli t0,0x9000000000000000 /* uncached - XKPHYS */
+ or reg_base,t0 /* so we can access flash beyond KSEG */
+#else
+ or reg_base,K1BASE /* 32-bit, regular KSEG */
+#endif
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+ bne reg_op,FEOP_RETURN,99f /* Return to main prog */
+
+ j ra
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_REBOOT,99f /* restart system */
+
+ li t0,0xBFC00000 /* jump to boot vector */
+ j t0
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_READ8,99f /* Read, 8-bit mode */
+
+ ADD reg_src,reg_src,reg_base
+
+1: lbu t0,0(reg_src) /* Copy user data */
+ sb t0,0(reg_dest)
+ ADD reg_src,1
+ add reg_dest,1
+ sub reg_cnt,1
+ bgt reg_cnt,zero,1b
+
+ b nextinst
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_READ16,99f /* Read, 16-bit mode */
+
+ ADD reg_src,reg_src,reg_base
+
+ li t0,1 /* test bottom bit */
+ and t0,t0,reg_src /* t0 == 1 if odd */
+ beq t0,zero,1f /* no odd byte to worry about */
+
+ SUB reg_src,reg_src,t0 /* make even value */
+ lh t0,0(reg_src) /* interesting byte is odd */
+#ifdef __MIPSEB
+ sb t0,0(reg_dest) /* interesting byte in low 8 bits */
+#else
+ srl t0,t0,8 /* little endian */
+ sb t0,0(reg_dest) /* interesting byte is high 8 bits */
+#endif
+
+ ADD reg_src,2 /* advance one word (we made addr even above) */
+ add reg_dest,1 /* dest always written by bytes */
+ sub reg_cnt,1
+
+1: beq reg_cnt,zero,nextinst
+
+ lh t0,0(reg_src) /* Copy user data */
+
+#ifdef __MIPSEB
+ sb t0,1(reg_dest) /* Big endian to memory */
+ srl t0,t0,8 /* t0 = 0x1234 -> 0x12 0x34 */
+ sb t0,0(reg_dest)
+#else
+ sb t0,0(reg_dest) /* little endian */
+ srl t0,t0,8 /* t0 = 0x1234 -> 0x34 0x12 */
+ sb t0,1(reg_dest)
+#endif
+
+ ADD reg_src,2
+ add reg_dest,2
+ sub reg_cnt,2
+ bgt reg_cnt,1,1b
+
+ beq reg_cnt,zero,nextinst /* no straggler */
+
+ lh t0,0(reg_src) /* interesting byte is odd */
+#ifdef __MIPSEB
+ srl t0,t0,8 /* little endian */
+ sb t0,0(reg_dest) /* interesting byte in high 8 bits */
+#else
+ sb t0,0(reg_dest) /* interesting byte is low 8 bits */
+#endif
+
+ b nextinst
+/* CFI - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+#if (FLASH_DRIVERS & FLASH_DRIVER_CFI)
+99: bne reg_op,FEOP_CFIQUERY8,99f /* CFI Query 8-bit */
+
+ ADD reg_src,reg_src,reg_base
+
+ FLASHCMD_8(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_MODE)
+
+1: lbu t0,0(reg_src) /* Copy CFI data */
+ sb t0,0(reg_dest)
+ ADD reg_src,1
+ add reg_dest,1
+ sub reg_cnt,1
+ bgt reg_cnt,zero,1b
+
+ FLASHCMD_8(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_EXIT)
+
+ b nextinst
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_CFIQUERY16,99f /* CFI Query 16-bit in word mode */
+
+ ADD reg_src,reg_src,reg_base
+
+ FLASHCMD_16(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_MODE)
+
+1: lh t0,0(reg_src) /* Copy CFI data */
+ sh t0,0(reg_dest)
+ ADD reg_src,2
+ add reg_dest,2
+ sub reg_cnt,2
+ bgt reg_cnt,zero,1b
+
+ FLASHCMD_16(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_EXIT)
+
+ b nextinst
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_CFIQUERY16B,99f /* CFI Query 16-bit in byte mode */
+
+ ADD reg_src,reg_src,reg_base
+
+ FLASHCMD_16B(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_MODE)
+
+1: lb t0,0(reg_src) /* Copy CFI data */
+ sb t0,0(reg_dest)
+ ADD reg_src,1
+ add reg_dest,1
+ sub reg_cnt,1
+ bgt reg_cnt,zero,1b
+
+ FLASHCMD_16B(reg_base,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_EXIT)
+
+ b nextinst
+#endif
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_MEMCPY,99f /* Generic memcpy */
+
+1: lbu t0,0(reg_src)
+ sb t0,0(reg_dest)
+ add reg_src,1
+ add reg_dest,1
+ sub reg_cnt,1
+ bgt reg_cnt,zero,1b
+
+ b nextinst
+
+
+/* AMD - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+#if (FLASH_DRIVERS & FLASH_DRIVER_AMD)
+99: bne reg_op,FEOP_AMD_ERASE8,99f /* AMD erase (8-bit) */
+
+ ADD reg_dest,reg_dest,reg_base
+
+ /* Do an "unlock write" sequence (cycles 1-2) */
+
+ FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+
+ /* send the erase command (cycle 3) */
+
+ FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3)
+
+ /* Do an "unlock write" sequence (cycles 4-5) */
+
+ FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+
+ /* Send the "erase sector" qualifier (cycle 6) */
+
+ FLASHCMD_8(reg_dest,0,AMD_FLASH_ERASE_SEC_6)
+
+ /* Wait for the erase to complete */
+
+1: lb t0,0(reg_dest) # get byte
+ and t0,0xFF # test hi byte
+ bne t0,0xFF,1b # go till bit is set
+
+ b nextinst
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_AMD_ERASE16,99f /* AMD erase (16-bit in word mode) */
+
+ ADD reg_dest,reg_dest,reg_base
+
+ /* Do an "unlock write" sequence (cycles 1-2) */
+
+ FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+
+ /* send the erase command (cycle 3) */
+
+ FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3)
+
+ /* Do an "unlock write" sequence (cycles 4-5) */
+
+ FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+
+ /* Send the "erase sector" qualifier (cycle 6) */
+
+ FLASHCMD_16(reg_dest,0,AMD_FLASH_ERASE_SEC_6)
+
+ /* Wait for the erase to complete */
+
+1: lh t0,0(reg_dest) # get word
+ and t0,0xFF # test byte
+ bne t0,0xFF,1b # go till erased
+
+ b nextinst
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_AMD_ERASE16B,99f /* AMD erase (16-bit in byte mode) */
+
+ ADD reg_dest,reg_dest,reg_base
+
+ /* Do an "unlock write" sequence (cycles 1-2) */
+
+ FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+
+ /* send the erase command (cycle 3) */
+
+ FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3)
+
+ /* Do an "unlock write" sequence (cycles 4-5) */
+
+ FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+
+ /* Send the "erase sector" qualifier (cycle 6) */
+
+ FLASHCMD_16B(reg_dest,0,AMD_FLASH_ERASE_SEC_6)
+
+ /* Wait for the erase to complete */
+
+1: lh t0,0(reg_dest) # get word
+ and t0,0xFF # test byte
+ bne t0,0xFF,1b # go till erased
+
+ b nextinst
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_AMD_PGM8,99f /* AMD 8-bit program */
+
+ ADD reg_dest,reg_dest,reg_base
+
+ /* Do an "unlock write" sequence (cycles 1-2) */
+11:
+ FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+
+ /* Send a program command (cycle 3) */
+
+ FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_PROGRAM)
+
+ /* Write a byte (cycle 4) */
+
+ lbu t0,0(reg_src)
+ sb t0,0(reg_dest) # t0 = byte written to flash
+
+ /* Wait for write to complete */
+
+1: lbu t2,0(reg_dest) # t2 = byte from flash
+
+ and t1,t2,0x80 # done if bit7 of flash
+ and t0,t0,0x80 # is same as bit7 of data
+ beq t1,t0,2f
+
+ and t1,t2,0x20 # not done if bit5
+ bne t1,0x20,1b # is still set
+2:
+
+ /* next byte... */
+
+ add reg_src,1 # next source byte
+ ADD reg_dest,1 # next dest byte
+ sub reg_cnt,1 # one less count
+ bgt reg_cnt,0,11b
+
+
+ b nextinst
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_AMD_PGM16,99f /* AMD 16-bit program */
+
+ ADD reg_dest,reg_dest,reg_base
+
+ /* Do an "unlock write" sequence (cycles 1-2) */
+11:
+ FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+
+ /* Send a program command (cycle 3) */
+
+ FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_PROGRAM)
+
+ /* Write a byte (cycle 4) */
+
+ lh t0,0(reg_src)
+ sh t0,0(reg_dest) # t0 = byte written to flash
+
+ /* Wait for write to complete */
+
+1: lh t2,0(reg_dest) # t2 = byte from flash
+
+ and t1,t2,0x80 # done if bit7 of flash
+ and t0,t0,0x80 # is same as bit7 of data
+ beq t1,t0,2f
+
+ and t1,t2,0x20 # not done if bit5
+ bne t1,0x20,1b # is still set
+2:
+
+ /* next byte... */
+
+ add reg_src,2 # next source word
+ ADD reg_dest,2 # next dest word
+ sub reg_cnt,2 # one less count
+ bgt reg_cnt,0,11b
+
+ b nextinst
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_AMD_PGM16B,99f /* AMD 16-bit pgm in 8-bit mode */
+
+ ADD reg_dest,reg_dest,reg_base
+
+ /* Do an "unlock write" sequence (cycles 1-2) */
+11:
+ FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+
+ /* Send a program command (cycle 3) */
+
+ FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_PROGRAM)
+
+ /* Write a byte (cycle 4) */
+
+ lb t0,0(reg_src)
+ sb t0,0(reg_dest) # t0 = byte written to flash
+
+ /* Wait for write to complete */
+
+1: lb t2,0(reg_dest) # t2 = byte from flash
+
+ and t1,t2,0x80 # done if bit7 of flash
+ and t0,t0,0x80 # is same as bit7 of data
+ beq t1,t0,2f
+
+ and t1,t2,0x20 # not done if bit5
+ bne t1,0x20,1b # is still set
+2:
+
+ /* next byte... */
+
+ add reg_src,1 # next source word
+ ADD reg_dest,1 # next dest word
+ sub reg_cnt,1 # one less count
+ bgt reg_cnt,0,11b
+
+ b nextinst
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_AMD_DEVCODE8,99f /* AMD 8-bit - Boot Block Location */
+
+ ADD reg_src,reg_src,reg_base
+
+ FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+ FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL)
+
+ lbu t0,AMD_FLASH_DEVCODE8(reg_src)
+ sb t0,0(reg_dest)
+ li t0,AMD_FLASH_RESET
+ sb t0,0(reg_src)
+
+
+ b nextinst
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_AMD_DEVCODE16,99f /* AMD 8-bit - Boot Block Location */
+
+ ADD reg_src,reg_src,reg_base
+
+ FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+ FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL)
+
+ lw t0,0(reg_src)
+#ifdef __MIPSEB
+ srl t0,t0,8 /* ((3-AMD_FLASH_DEVCODE16)*8) */
+#else
+ srl t0,t0,16 /* (AMD_FLASH_DEVCODE16*8) */
+#endif
+ sb t0,0(reg_dest)
+ li t0,AMD_FLASH_RESET
+ sb t0,0(reg_src)
+
+ b nextinst
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_AMD_DEVCODE16B,99f /* AMD 8-bit - Boot Block Location */
+
+ ADD reg_src,reg_src,reg_base
+
+ FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+ FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL)
+
+ lw t0,0(reg_src)
+#ifdef __MIPSEB
+#else
+ srl t0,t0,16 /* (AMD_FLASH_DEVCODE16B*8)*/
+#endif
+
+ sb t0,0(reg_dest)
+ li t0,AMD_FLASH_RESET
+ sb t0,0(reg_src)
+
+ b nextinst
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_AMD_MANID8,99f /* AMD 8-bit - Boot Block Location */
+
+ ADD reg_src,reg_src,reg_base
+
+ FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+ FLASHCMD_8(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL)
+
+ lbu t0,AMD_FLASH_MANID(reg_src)
+ sb t0,0(reg_dest)
+ li t0,AMD_FLASH_RESET
+ sb t0,0(reg_src)
+
+
+ b nextinst
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_AMD_MANID16,99f /* AMD 8-bit - Boot Block Location */
+
+ ADD reg_src,reg_src,reg_base
+
+ FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+ FLASHCMD_16(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL)
+
+ lw t0,0(reg_src)
+#ifdef __MIPSEB
+ srl t0,t0,((3-AMD_FLASH_MANID)*8)
+#else
+ srl t0,t0,(AMD_FLASH_MANID*8)
+#endif
+ sb t0,0(reg_dest)
+ li t0,AMD_FLASH_RESET
+ sb t0,0(reg_src)
+
+ b nextinst
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_AMD_MANID16B,99f /* AMD 8-bit - Boot Block Location */
+
+ ADD reg_src,reg_src,reg_base
+
+ FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1)
+ FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2)
+ FLASHCMD_16B(reg_base,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL)
+
+ lbu t0,AMD_FLASH_MANID(reg_src)
+
+ sb t0,0(reg_dest)
+ li t0,AMD_FLASH_RESET
+ sb t0,0(reg_src)
+
+ b nextinst
+
+#endif
+
+/* INTEL - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+#if (FLASH_DRIVERS & FLASH_DRIVER_INTEL)
+99: bne reg_op,FEOP_INTEL_ERASE8,99f /* Intel erase 8-bit */
+
+ ADD reg_dest,reg_dest,reg_base
+
+ FLASHCMD_8(reg_dest,0,INTEL_FLASH_ERASE_BLOCK)
+ FLASHCMD_8(reg_dest,0,INTEL_FLASH_ERASE_CONFIRM)
+
+1: lbu t0,0(reg_dest) /* loop till bit 7 is set */
+ andi t0,0x80
+ beq t0,zero,1b
+
+ FLASHCMD_8(reg_dest,0,INTEL_FLASH_READ_MODE)
+
+ b nextinst
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_INTEL_ERASE16,99f /* Intel erase 16-bit */
+
+ ADD reg_dest,reg_dest,reg_base
+
+/* XXX copy of 8-bit erase, is this right? */
+
+ FLASHCMD_8(reg_dest,0,INTEL_FLASH_ERASE_BLOCK)
+ FLASHCMD_8(reg_dest,0,INTEL_FLASH_ERASE_CONFIRM)
+
+1: lbu t0,0(reg_dest) /* loop till bit 7 is set */
+ andi t0,0x80
+ beq t0,zero,1b
+
+ FLASHCMD_8(reg_dest,0,INTEL_FLASH_READ_MODE)
+
+ b nextinst
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_INTEL_PGM8,99f /* Intel 8-bit program */
+
+ ADD reg_dest,reg_dest,reg_base
+
+11: FLASHCMD_8(reg_dest,0,INTEL_FLASH_PROGRAM)
+
+ lbu t0,0(reg_src)
+ sb t0,0(reg_dest)
+
+1: lbu t0,0(reg_dest) /* loop till bit 7 is set */
+ andi t0,0x80
+ beq t0,zero,1b
+
+ lbu t0,0(reg_dest) /* contains final result */
+ /* If good, bits 1, 3, 4 will not be set */
+
+ add reg_src,1
+ ADD reg_dest,1
+ sub reg_cnt,1
+ bgt reg_cnt,zero,11b
+
+ FLASHCMD_8(reg_dest,0,INTEL_FLASH_READ_MODE)
+
+ b nextinst
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: bne reg_op,FEOP_INTEL_PGM16,99f /* Intel 16-bit prog */
+
+ ADD reg_dest,reg_dest,reg_base
+
+11: FLASHCMD_16(reg_dest,0,INTEL_FLASH_PROGRAM)
+
+ lh t0,0(reg_src)
+ sh t0,0(reg_dest)
+
+1: lh t0,0(reg_dest) /* loop till bit 7 is set */
+ andi t0,0x80
+ beq t0,zero,1b
+
+ lh t0,0(reg_dest) /* contains final result */
+ /* If good, bits 1, 3, 4 will not be set */
+
+ add reg_src,2
+ ADD reg_dest,2
+ sub reg_cnt,2
+ bgt reg_cnt,zero,11b
+
+ FLASHCMD_16(reg_dest,0,INTEL_FLASH_READ_MODE)
+
+ b nextinst
+#endif
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+99: li v1,-1 /* invalid command */
+
+nextinst: SR v1,FEINST_RESULT(a0) /* store result of instruction */
+ ADD v0,v0,v1 /* add to total */
+ ADD a0,FEINST_SIZE /* advance to next instr. */
+ b instloop
+
+flashop_engine_end:
+ nop
+
+END(flashop_engine)
+
+ .sdata
+
+ .globl flashop_engine_ptr
+ .globl flashop_engine_len
+
+flashop_engine_ptr:
+ _VECT_ flashop_engine
+flashop_engine_len:
+ .word flashop_engine_end-flashop_engine
+
+
+
+/* *********************************************************************
+ * end
+ ********************************************************************* */
+
+
diff --git a/cfe/cfe/arch/mips/common/src/disasm.c b/cfe/cfe/arch/mips/common/src/disasm.c
new file mode 100644
index 0000000..1b76fee
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/disasm.c
@@ -0,0 +1,2111 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * MIPS disassembler File: disasm.c
+ *
+ * MIPS disassembler (used by ui_examcmds.c)
+ *
+ * Author: Justin Carlson (carlson@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "disasm.h"
+#include "lib_printf.h"
+
+#define UINT64_T(x) ((uint64_t) (x))
+#define PF_64 "ll"
+#define PF_32 ""
+/* These aren't guaranteed to be portable, either */
+#define SEXT_32(bit, val) \
+ ((((int32_t)(val))<<(31-(bit)))>>(31-(bit)))
+#define SEXT_64(bit, val) \
+ ((((int64_t)(val))<<(63-(bit)))>>(63-(bit)))
+
+#define DATASEG __attribute__ ((section(".text")))
+
+
+#define REGNAME(r) (&_regnames[(r)*5])
+static const char * const _regnames =
+ "zero\0"
+ "AT\0 "
+ "v0\0 "
+ "v1\0 "
+ "a0\0 "
+ "a1\0 "
+ "a2\0 "
+ "a3\0 "
+ "t0\0 "
+ "t1\0 "
+ "t2\0 "
+ "t3\0 "
+ "t4\0 "
+ "t5\0 "
+ "t6\0 "
+ "t7\0 "
+ "s0\0 "
+ "s1\0 "
+ "s2\0 "
+ "s3\0 "
+ "s4\0 "
+ "s5\0 "
+ "s6\0 "
+ "s7\0 "
+ "t8\0 "
+ "t9\0 "
+ "k0\0 "
+ "k1\0 "
+ "gp\0 "
+ "sp\0 "
+ "fp\0 "
+ "ra\0 ";
+
+#define CP0REGNAME(r) (&_cp0names[(r)*12])
+static const char * const _cp0names =
+ "C0_INX\0 "
+ "C0_RAND\0 "
+ "C0_TLBLO0\0 "
+ "C0_TLBLO1\0 "
+
+ "C0_CTEXT\0 "
+ "C0_PGMASK\0 "
+ "C0_WIRED\0 "
+ "C0_reserved\0"
+
+ "C0_BADVADDR\0"
+ "C0_COUNT\0 "
+ "C0_TLBHI\0 "
+ "C0_COMPARE\0 "
+
+ "C0_SR\0 "
+ "C0_CAUSE\0 "
+ "C0_EPC\0 "
+ "C0_PRID\0 "
+
+ "C0_CONFIG\0 "
+ "C0_LLADDR\0 "
+ "C0_WATCHLO\0 "
+ "C0_WATCHHI\0 "
+
+ "C0_XCTEXT\0 "
+ "C0_reserved\0"
+ "C0_reserved\0"
+ "C0_reserved\0"
+
+ "C0_reserved\0"
+ "C0_reserved\0"
+ "C0_reserved\0"
+ "C0_reserved\0"
+
+ "C0_TAGLO\0 "
+ "C0_TAGHI\0 "
+ "C0_ERREPC\0 "
+ "C0_reserved\0";
+
+
+
+/*
+ * MIPS instruction set disassembly module.
+ */
+
+typedef enum {
+ DC_RD_RS_RT,
+ DC_RD_RT_RS,
+ DC_RT_RS_SIMM,
+ DC_RT_RS_XIMM,
+ DC_RS_RT_OFS,
+ DC_RS_OFS,
+ DC_RD_RT_SA,
+ DC_RT_UIMM,
+ DC_RD,
+ DC_J,
+ DC_RD_RS,
+ DC_RS_RT,
+ DC_RT_RS,
+ DC_RT_RD_SEL,
+ DC_RT_CR_SEL,
+ DC_RS,
+ DC_RS_SIMM,
+ DC_RT_OFS_BASE,
+ DC_FT_OFS_BASE,
+ DC_FD_IDX_BASE,
+ DC_FS_IDX_BASE,
+ DC_FD_FS_FT,
+ DC_FD_FS_RT,
+ DC_FD_FS,
+ DC_PREF_OFS,
+ DC_PREF_IDX,
+ DC_CC_OFS,
+ DC_FD_FS_CC,
+ DC_RD_RS_CC,
+ DC_FD_FR_FS_FT,
+ DC_FD_FS_FT_RS,
+ DC_CC_FS_FT,
+ DC_BARE,
+ DC_RT_FS,
+ DC_SYSCALL,
+ DC_BREAK,
+ DC_VD_VS_VT_VEC,
+ DC_VD_VS_VT,
+ DC_VS_VT,
+ DC_VS_VT_VEC,
+ DC_VD_VS_VT_RS,
+ DC_VD_VS_VT_IMM,
+ DC_VD_VT,
+ DC_VD,
+ DC_VS,
+ DC_DEREF,
+ DC_OOPS
+} DISASM_CLASS;
+
+
+
+
+/* We're pulling some trickery here. Most of the time, this structure operates
+ exactly as one would expect. The special case, when type == DC_DREF,
+ means name points to a byte that is an index into a dereferencing array. */
+
+/*
+ * To make matters worse, the whole module has been coded to reduce the
+ * number of relocations present, so we don't actually store pointers
+ * in the dereferencing array. Instead, we store fixed-width strings
+ * and use digits to represent indicies into the deref array.
+ *
+ * This is all to make more things fit in the relocatable version,
+ * since every initialized pointer goes into our small data segment.
+ */
+
+typedef struct {
+ char name[15];
+ char type;
+} disasm_t;
+
+typedef struct {
+ const disasm_t *ptr;
+ int shift;
+ uint32_t mask;
+} disasm_deref_t;
+
+/* Forward declaration of deref array, we need this for the disasm_t definitions */
+
+
+extern const disasm_deref_t disasm_deref[];
+
+static const disasm_t disasm_normal[64] DATASEG =
+{{"$1" , DC_DEREF },
+ {"$2" , DC_DEREF },
+ {"j" , DC_J },
+ {"jal" , DC_J },
+ {"beq" , DC_RS_RT_OFS },
+ {"bne" , DC_RS_RT_OFS },
+ {"blez" , DC_RS_OFS },
+ {"bgtz" , DC_RS_OFS },
+ {"addi" , DC_RT_RS_SIMM },
+ {"addiu" , DC_RT_RS_SIMM },
+ {"slti" , DC_RT_RS_SIMM },
+ {"sltiu" , DC_RT_RS_SIMM },
+ {"andi" , DC_RT_RS_XIMM },
+ {"ori" , DC_RT_RS_XIMM },
+ {"xori" , DC_RT_RS_XIMM },
+ {"lui" , DC_RT_UIMM },
+ {"$4" , DC_DEREF },
+ {"$6" , DC_DEREF },
+ {"invalid" , DC_BARE },
+ {"$15" , DC_DEREF },
+ {"beql" , DC_RS_RT_OFS },
+ {"bnel" , DC_RS_RT_OFS },
+ {"blezl" , DC_RS_OFS },
+ {"bgtzl" , DC_RS_OFS },
+ {"daddi" , DC_RT_RS_SIMM },
+ {"daddiu" , DC_RT_RS_SIMM },
+ {"ldl" , DC_RT_OFS_BASE },
+ {"ldr" , DC_RT_OFS_BASE },
+ {"$3" , DC_DEREF },
+ {"invalid" , DC_BARE },
+ {"$18" , DC_DEREF },
+ {"invalid" , DC_BARE },
+ {"lb" , DC_RT_OFS_BASE },
+ {"lh" , DC_RT_OFS_BASE },
+ {"lwl" , DC_RT_OFS_BASE },
+ {"lw" , DC_RT_OFS_BASE },
+ {"lbu" , DC_RT_OFS_BASE },
+ {"lhu" , DC_RT_OFS_BASE },
+ {"lwr" , DC_RT_OFS_BASE },
+ {"lwu" , DC_RT_OFS_BASE },
+ {"sb" , DC_RT_OFS_BASE },
+ {"sh" , DC_RT_OFS_BASE },
+ {"swl" , DC_RT_OFS_BASE },
+ {"sw" , DC_RT_OFS_BASE },
+ {"sdl" , DC_RT_OFS_BASE },
+ {"sdr" , DC_RT_OFS_BASE },
+ {"swr" , DC_RT_OFS_BASE },
+ {"cache" , DC_BARE },
+ {"ll" , DC_RT_OFS_BASE },
+ {"lwc1" , DC_FT_OFS_BASE },
+ {"invalid" , DC_BARE },
+ {"pref" , DC_PREF_OFS },
+ {"lld" , DC_RT_OFS_BASE },
+ {"ldc1" , DC_FT_OFS_BASE },
+ {"invalid" , DC_BARE },
+ {"ld" , DC_RT_OFS_BASE },
+ {"sc" , DC_RT_OFS_BASE },
+ {"swc1" , DC_FT_OFS_BASE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"scd" , DC_RT_OFS_BASE },
+ {"sdc1" , DC_FT_OFS_BASE },
+ {"invalid" , DC_BARE },
+ {"sd" , DC_RT_OFS_BASE }};
+
+static const disasm_t disasm_special[64] DATASEG =
+{{"sll" , DC_RD_RT_SA },
+ {"$16" , DC_DEREF },
+ {"srl" , DC_RD_RT_SA },
+ {"sra" , DC_RD_RT_SA },
+ {"sllv" , DC_RD_RT_RS },
+ {"invalid" , DC_BARE },
+ {"srlv" , DC_RD_RT_RS },
+ {"srav" , DC_RD_RT_RS },
+ {"jr" , DC_RS },
+ {"jalr" , DC_RD_RS },
+ {"movz" , DC_RD_RS_RT },
+ {"movn" , DC_RD_RS_RT },
+ {"syscall" , DC_SYSCALL },
+ {"break" , DC_BREAK },
+ {"invalid" , DC_BARE },
+ {"sync" , DC_BARE },
+ {"mfhi" , DC_RD },
+ {"mthi" , DC_RS },
+ {"mflo" , DC_RD },
+ {"mtlo" , DC_RS },
+ {"dsllv" , DC_RD_RT_RS },
+ {"invalid" , DC_BARE },
+ {"dsrlv" , DC_RD_RT_RS },
+ {"dsrav" , DC_RD_RT_RS },
+ {"mult" , DC_RS_RT },
+ {"multu" , DC_RS_RT },
+ {"div" , DC_RS_RT },
+ {"divu" , DC_RS_RT },
+ {"dmult" , DC_RS_RT },
+ {"dmultu" , DC_RS_RT },
+ {"ddiv" , DC_RS_RT },
+ {"ddivu" , DC_RS_RT },
+ {"add" , DC_RD_RS_RT },
+ {"addu" , DC_RD_RS_RT },
+ {"sub" , DC_RD_RS_RT },
+ {"subu" , DC_RD_RS_RT },
+ {"and" , DC_RD_RS_RT },
+ {"or" , DC_RD_RS_RT },
+ {"xor" , DC_RD_RS_RT },
+ {"nor" , DC_RD_RS_RT },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"slt" , DC_RD_RS_RT },
+ {"sltu" , DC_RD_RS_RT },
+ {"dadd" , DC_RD_RS_RT },
+ {"daddu" , DC_RD_RS_RT },
+ {"dsub" , DC_RD_RS_RT },
+ {"dsubu" , DC_RD_RS_RT },
+ {"tge" , DC_RS_RT },
+ {"tgeu" , DC_RS_RT },
+ {"tlt" , DC_RS_RT },
+ {"tltu" , DC_RS_RT },
+ {"teq" , DC_RS_RT },
+ {"invalid" , DC_BARE },
+ {"tne" , DC_RS_RT },
+ {"invalid" , DC_BARE },
+ {"dsll" , DC_RD_RT_SA },
+ {"invalid" , DC_BARE },
+ {"dsrl" , DC_RD_RT_SA },
+ {"dsra" , DC_RD_RT_SA },
+ {"dsll32" , DC_RD_RT_SA },
+ {"invalid" , DC_BARE },
+ {"dsrl32" , DC_RD_RT_SA },
+ {"dsra32" , DC_RD_RT_SA }};
+
+static const disasm_t disasm_movci[2] DATASEG =
+{{"movf" , DC_RD_RS_CC },
+ {"movt" , DC_RD_RS_CC }};
+
+static const disasm_t disasm_regimm[32] DATASEG =
+{{"bltz" , DC_RS_OFS },
+ {"bgez" , DC_RS_OFS },
+ {"bltzl" , DC_RS_OFS },
+ {"bgezl" , DC_RS_OFS },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"tgei" , DC_RS_SIMM },
+ {"tgeiu" , DC_RS_SIMM },
+ {"tlti" , DC_RS_SIMM },
+ {"tltiu" , DC_RS_SIMM },
+ {"teqi" , DC_RS_SIMM },
+ {"invalid" , DC_BARE },
+ {"tnei" , DC_RS_SIMM },
+ {"invalid" , DC_BARE },
+ {"bltzal" , DC_RS_OFS },
+ {"bgezal" , DC_RS_OFS },
+ {"bltzall" , DC_RS_OFS },
+ {"bgezall" , DC_RS_OFS },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE }};
+
+static const disasm_t disasm_spec2[64] DATASEG =
+{{"madd" , DC_RS_RT },
+ {"maddu" , DC_RS_RT },
+ {"mul" , DC_RD_RS_RT },
+ {"invalid" , DC_BARE },
+ {"msub" , DC_RS_RT },
+ {"msubu" , DC_RS_RT },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"clz" , DC_RT_RS },
+ {"clo" , DC_RT_RS },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"dclz" , DC_RT_RS },
+ {"dclo" , DC_RT_RS },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"sdbbp" , DC_BARE }};
+
+static const disasm_t disasm_cop0[32] DATASEG =
+{{"mfc0@1" , DC_RT_CR_SEL },
+ {"dmfc0@1" , DC_RT_CR_SEL },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"mtc0@1" , DC_RT_CR_SEL },
+ {"dmtc0@1" , DC_RT_CR_SEL },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"$5" , DC_DEREF },
+ {"$5" , DC_DEREF },
+ {"$5" , DC_DEREF },
+ {"$5" , DC_DEREF },
+ {"$5" , DC_DEREF },
+ {"$5" , DC_DEREF },
+ {"$5" , DC_DEREF },
+ {"$5" , DC_DEREF },
+ {"$5" , DC_DEREF },
+ {"$5" , DC_DEREF },
+ {"$5" , DC_DEREF },
+ {"$5" , DC_DEREF },
+ {"$5" , DC_DEREF },
+ {"$5" , DC_DEREF },
+ {"$5" , DC_DEREF },
+ {"$5" , DC_DEREF }};
+
+static const disasm_t disasm_cop0_c0[64] DATASEG =
+{{"invalid" , DC_BARE },
+ {"tlbr" , DC_BARE },
+ {"tlbwi" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"tlbwr" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"tlbp" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"eret" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"deret" , DC_BARE },
+ {"wait" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE }};
+
+static const disasm_t disasm_cop1[32] DATASEG =
+{{"mfc1" , DC_RT_FS },
+ {"dmfc1" , DC_RT_FS },
+ {"cfc1" , DC_RT_FS },
+ {"invalid" , DC_BARE },
+ {"mtc1" , DC_RT_FS },
+ {"dmtc1" , DC_RT_FS },
+ {"ctc1" , DC_RT_FS },
+ {"invalid" , DC_BARE },
+ {"$17" , DC_DEREF },
+ {"$36" , DC_DEREF },
+ {"$37" , DC_DEREF },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"$7" , DC_DEREF },
+ {"$9" , DC_DEREF },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"$11" , DC_DEREF },
+ {"$12" , DC_DEREF },
+ {"$13" , DC_DEREF },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE }};
+
+static const disasm_t disasm_cop1_bc1[4] DATASEG =
+{{"bc1f" , DC_CC_OFS },
+ {"bc1t" , DC_CC_OFS },
+ {"bc1fl" , DC_CC_OFS },
+ {"bc1tl" , DC_CC_OFS },
+};
+
+static const disasm_t disasm_cop1_bc1any2[2] DATASEG =
+{{"bc1any2f" , DC_CC_OFS },
+ {"bc1any2t" , DC_CC_OFS },
+};
+
+static const disasm_t disasm_cop1_bc1any4[2] DATASEG =
+{{"bc1any4f" , DC_CC_OFS },
+ {"bc1any4t" , DC_CC_OFS },
+};
+
+static const disasm_t disasm_cop1_s[64] DATASEG =
+{{"add.s" , DC_FD_FS_FT },
+ {"sub.s" , DC_FD_FS_FT },
+ {"mul.s" , DC_FD_FS_FT },
+ {"div.s" , DC_FD_FS_FT },
+ {"sqrt.s" , DC_FD_FS },
+ {"abs.s" , DC_FD_FS },
+ {"mov.s" , DC_FD_FS },
+ {"neg.s" , DC_FD_FS },
+ {"round.l.s" , DC_FD_FS },
+ {"trunc.l.s" , DC_FD_FS },
+ {"ceil.l.s" , DC_FD_FS },
+ {"floor.l.s" , DC_FD_FS },
+ {"round.w.s" , DC_FD_FS },
+ {"trunc.w.s" , DC_FD_FS },
+ {"ceil.w.s" , DC_FD_FS },
+ {"floor.w.s" , DC_FD_FS },
+ {"invalid" , DC_BARE },
+ {"$8" , DC_DEREF },
+ {"movz.s" , DC_FD_FS_RT },
+ {"movn.s" , DC_FD_FS_RT },
+ {"invalid" , DC_BARE },
+ {"recip.s" , DC_FD_FS },
+ {"rsqrt.s" , DC_FD_FS },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"recip2.s" , DC_FD_FS_FT },
+ {"recip1.s" , DC_FD_FS },
+ {"rsqrt1.s" , DC_FD_FS },
+ {"rsqrt2.s" , DC_FD_FS_FT },
+ {"invalid" , DC_BARE },
+ {"cvt.d.s" , DC_FD_FS },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"cvt.w.s" , DC_FD_FS },
+ {"cvt.l.s" , DC_FD_FS },
+ {"cvt.ps.s" , DC_FD_FS_FT },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"$38" , DC_DEREF },
+ {"$39" , DC_DEREF },
+ {"$40" , DC_DEREF },
+ {"$41" , DC_DEREF },
+ {"$42" , DC_DEREF },
+ {"$43" , DC_DEREF },
+ {"$44" , DC_DEREF },
+ {"$45" , DC_DEREF },
+ {"$46" , DC_DEREF },
+ {"$47" , DC_DEREF },
+ {"$48" , DC_DEREF },
+ {"$49" , DC_DEREF },
+ {"$50" , DC_DEREF },
+ {"$51" , DC_DEREF },
+ {"$52" , DC_DEREF },
+ {"$53" , DC_DEREF }};
+
+static const disasm_t disasm_cop1_s_mvcf[2] DATASEG =
+{{"movf.s" , DC_FD_FS_CC },
+ {"movt.s" , DC_FD_FS_CC }};
+
+static const disasm_t disasm_cop1_d[64] DATASEG =
+{{"add.d" , DC_FD_FS_FT },
+ {"sub.d" , DC_FD_FS_FT },
+ {"mul.d" , DC_FD_FS_FT },
+ {"div.d" , DC_FD_FS_FT },
+ {"sqrt.d" , DC_FD_FS },
+ {"abs.d" , DC_FD_FS },
+ {"mov.d" , DC_FD_FS },
+ {"neg.d" , DC_FD_FS },
+ {"round.l.d" , DC_FD_FS },
+ {"trunc.l.d" , DC_FD_FS },
+ {"ceil.l.d" , DC_FD_FS },
+ {"floor.l.d" , DC_FD_FS },
+ {"round.w.d" , DC_FD_FS },
+ {"trunc.w.d" , DC_FD_FS },
+ {"ceil.w.d" , DC_FD_FS },
+ {"floor.w.d" , DC_FD_FS },
+ {"invalid" , DC_BARE },
+ {"$10" , DC_DEREF },
+ {"movz.d" , DC_FD_FS_RT },
+ {"movn.d" , DC_FD_FS_RT },
+ {"invalid" , DC_BARE },
+ {"recip.d" , DC_FD_FS },
+ {"rsqrt.d" , DC_FD_FS },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"recip2.d" , DC_FD_FS_FT },
+ {"recip1.d" , DC_FD_FS },
+ {"rsqrt1.d" , DC_FD_FS },
+ {"rsqrt2.d" , DC_FD_FS_FT },
+ {"cvt.s.d" , DC_FD_FS },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"cvt.w.d" , DC_FD_FS },
+ {"cvt.l.d" , DC_FD_FS },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"$54" , DC_DEREF },
+ {"$55" , DC_DEREF },
+ {"$56" , DC_DEREF },
+ {"$57" , DC_DEREF },
+ {"$58" , DC_DEREF },
+ {"$59" , DC_DEREF },
+ {"$60" , DC_DEREF },
+ {"$61" , DC_DEREF },
+ {"$62" , DC_DEREF },
+ {"$63" , DC_DEREF },
+ {"$64" , DC_DEREF },
+ {"$65" , DC_DEREF },
+ {"$66" , DC_DEREF },
+ {"$67" , DC_DEREF },
+ {"$68" , DC_DEREF },
+ {"$69" , DC_DEREF }};
+
+static const disasm_t disasm_cop1_d_mvcf[2] DATASEG =
+{{"movf.d" , DC_FD_FS_CC },
+ {"movt.d" , DC_FD_FS_CC }};
+
+static const disasm_t disasm_cop1_w[64] DATASEG =
+{{"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"cvt.s.w" , DC_FD_FS },
+ {"cvt.d.w" , DC_FD_FS },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"cvt.ps.pw" , DC_FD_FS },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE }};
+
+static const disasm_t disasm_cop1_l[64] DATASEG =
+{{"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"cvt.s.l" , DC_FD_FS },
+ {"cvt.d.l" , DC_FD_FS },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE }};
+
+static const disasm_t disasm_cop1_ps[64] DATASEG =
+{{"add.ps" , DC_FD_FS_FT },
+ {"sub.ps" , DC_FD_FS_FT },
+ {"mul.ps" , DC_FD_FS_FT },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"abs.ps" , DC_FD_FS },
+ {"mov.ps" , DC_FD_FS },
+ {"neg.ps" , DC_FD_FS },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"$14" , DC_DEREF },
+ {"movz.ps" , DC_FD_FS_RT },
+ {"movn.ps" , DC_FD_FS_RT },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"addr.ps" , DC_FD_FS_FT },
+ {"invalid" , DC_BARE },
+ {"mulr.ps" , DC_FD_FS_FT },
+ {"invalid" , DC_BARE },
+ {"recip2.ps" , DC_FD_FS_FT },
+ {"recip1.ps" , DC_FD_FS },
+ {"rsqrt1.ps" , DC_FD_FS },
+ {"rsqrt2.ps" , DC_FD_FS_FT },
+ {"cvt.s.pu" , DC_FD_FS },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"cvt.pw.ps" , DC_FD_FS },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"cvt.s.pl" , DC_FD_FS },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"pll.ps" , DC_FD_FS_FT },
+ {"plu.ps" , DC_FD_FS_FT },
+ {"pul.ps" , DC_FD_FS_FT },
+ {"puu.ps" , DC_FD_FS_FT },
+ {"$70" , DC_DEREF },
+ {"$71" , DC_DEREF },
+ {"$72" , DC_DEREF },
+ {"$73" , DC_DEREF },
+ {"$74" , DC_DEREF },
+ {"$75" , DC_DEREF },
+ {"$76" , DC_DEREF },
+ {"$77" , DC_DEREF },
+ {"$78" , DC_DEREF },
+ {"$79" , DC_DEREF },
+ {"$80" , DC_DEREF },
+ {"$81" , DC_DEREF },
+ {"$82" , DC_DEREF },
+ {"$83" , DC_DEREF },
+ {"$84" , DC_DEREF },
+ {"$85" , DC_DEREF }};
+
+static const disasm_t disasm_cop1_c_f_s[2] DATASEG =
+{{"c.f.s" , DC_CC_FS_FT },
+ {"cabs.f.s" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_un_s[2] DATASEG =
+{{"c.un.s" , DC_CC_FS_FT },
+ {"cabs.un.s" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_eq_s[2] DATASEG =
+{{"c.eq.s" , DC_CC_FS_FT },
+ {"cabs.eq.s" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ueq_s[2] DATASEG =
+{{"c.ueq.s" , DC_CC_FS_FT },
+ {"cabs.ueq.s" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_olt_s[2] DATASEG =
+{{"c.olt.s" , DC_CC_FS_FT },
+ {"cabs.olt.s" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ult_s[2] DATASEG =
+{{"c.ult.s" , DC_CC_FS_FT },
+ {"cabs.ult.s" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ole_s[2] DATASEG =
+{{"c.ole.s" , DC_CC_FS_FT },
+ {"cabs.ole.s" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ule_s[2] DATASEG =
+{{"c.ule.s" , DC_CC_FS_FT },
+ {"cabs.ule.s" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_sf_s[2] DATASEG =
+{{"c.sf.s" , DC_CC_FS_FT },
+ {"cabs.sf.s" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ngle_s[2] DATASEG =
+{{"c.ngle.s" , DC_CC_FS_FT },
+ {"cabs.ngle.s" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_seq_s[2] DATASEG =
+{{"c.seq.s" , DC_CC_FS_FT },
+ {"cabs.seq.s" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ngl_s[2] DATASEG =
+{{"c.ngl.s" , DC_CC_FS_FT },
+ {"cabs.ngl.s" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_lt_s[2] DATASEG =
+{{"c.lt.s" , DC_CC_FS_FT },
+ {"cabs.lt.s" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_nge_s[2] DATASEG =
+{{"c.nge.s" , DC_CC_FS_FT },
+ {"cabs.nge.s" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_le_s[2] DATASEG =
+{{"c.le.s" , DC_CC_FS_FT },
+ {"cabs.le.s" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ngt_s[2] DATASEG =
+{{"c.ngt.s" , DC_CC_FS_FT },
+ {"cabs.ngt.s" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_f_d[2] DATASEG =
+{{"c.f.d" , DC_CC_FS_FT },
+ {"cabs.f.d" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_un_d[2] DATASEG =
+{{"c.un.d" , DC_CC_FS_FT },
+ {"cabs.un.d" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_eq_d[2] DATASEG =
+{{"c.eq.d" , DC_CC_FS_FT },
+ {"cabs.eq.d" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ueq_d[2] DATASEG =
+{{"c.ueq.d" , DC_CC_FS_FT },
+ {"cabs.ueq.d" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_olt_d[2] DATASEG =
+{{"c.olt.d" , DC_CC_FS_FT },
+ {"cabs.olt.d" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ult_d[2] DATASEG =
+{{"c.ult.d" , DC_CC_FS_FT },
+ {"cabs.ult.d" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ole_d[2] DATASEG =
+{{"c.ole.d" , DC_CC_FS_FT },
+ {"cabs.ole.d" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ule_d[2] DATASEG =
+{{"c.ule.d" , DC_CC_FS_FT },
+ {"cabs.ule.d" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_sf_d[2] DATASEG =
+{{"c.sf.d" , DC_CC_FS_FT },
+ {"cabs.sf.d" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ngle_d[2] DATASEG =
+{{"c.ngle.d" , DC_CC_FS_FT },
+ {"cabs.ngle.d" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_seq_d[2] DATASEG =
+{{"c.seq.d" , DC_CC_FS_FT },
+ {"cabs.seq.d" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ngl_d[2] DATASEG =
+{{"c.ngl.d" , DC_CC_FS_FT },
+ {"cabs.ngl.d" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_lt_d[2] DATASEG =
+{{"c.lt.d" , DC_CC_FS_FT },
+ {"cabs.lt.d" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_nge_d[2] DATASEG =
+{{"c.nge.d" , DC_CC_FS_FT },
+ {"cabs.nge.d" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_le_d[2] DATASEG =
+{{"c.le.d" , DC_CC_FS_FT },
+ {"cabs.le.d" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ngt_d[2] DATASEG =
+{{"c.ngt.d" , DC_CC_FS_FT },
+ {"cabs.ngt.d" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_f_ps[2] DATASEG =
+{{"c.f.ps" , DC_CC_FS_FT },
+ {"cabs.f.ps" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_un_ps[2] DATASEG =
+{{"c.un.ps" , DC_CC_FS_FT },
+ {"cabs.un.ps" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_eq_ps[2] DATASEG =
+{{"c.eq.ps" , DC_CC_FS_FT },
+ {"cabs.eq.ps" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ueq_ps[2] DATASEG =
+{{"c.ueq.ps" , DC_CC_FS_FT },
+ {"cabs.ueq.ps" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_olt_ps[2] DATASEG =
+{{"c.olt.ps" , DC_CC_FS_FT },
+ {"cabs.olt.ps" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ult_ps[2] DATASEG =
+{{"c.ult.ps" , DC_CC_FS_FT },
+ {"cabs.ult.ps" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ole_ps[2] DATASEG =
+{{"c.ole.ps" , DC_CC_FS_FT },
+ {"cabs.ole.ps" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ule_ps[2] DATASEG =
+{{"c.ule.ps" , DC_CC_FS_FT },
+ {"cabs.ule.ps" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_sf_ps[2] DATASEG =
+{{"c.sf.ps" , DC_CC_FS_FT },
+ {"cabs.sf.ps" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ngle_ps[2] DATASEG =
+{{"c.ngle.ps" , DC_CC_FS_FT },
+ {"cabs.ngle.ps" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_seq_ps[2] DATASEG =
+{{"c.seq.ps" , DC_CC_FS_FT },
+ {"cabs.seq.ps" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ngl_ps[2] DATASEG =
+{{"c.ngl.ps" , DC_CC_FS_FT },
+ {"cabs.ngl.ps" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_lt_ps[2] DATASEG =
+{{"c.lt.ps" , DC_CC_FS_FT },
+ {"cabs.lt.ps" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_nge_ps[2] DATASEG =
+{{"c.nge.ps" , DC_CC_FS_FT },
+ {"cabs.nge.ps" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_le_ps[2] DATASEG =
+{{"c.le.ps" , DC_CC_FS_FT },
+ {"cabs.le.ps" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_c_ngt_ps[2] DATASEG =
+{{"c.ngt.ps" , DC_CC_FS_FT },
+ {"cabs.ngt.ps" , DC_CC_FS_FT }};
+
+static const disasm_t disasm_cop1_ps_mvcf[2] DATASEG =
+{{"movf.ps" , DC_FD_FS_CC },
+ {"movt.ps" , DC_FD_FS_CC }};
+
+static const disasm_t disasm_cop1x[64] DATASEG =
+{{"lwxc1" , DC_FD_IDX_BASE },
+ {"ldxc1" , DC_FD_IDX_BASE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"luxc1" , DC_FD_IDX_BASE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"swxc1" , DC_FS_IDX_BASE },
+ {"sdxc1" , DC_FS_IDX_BASE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"suxc1" , DC_FS_IDX_BASE },
+ {"invalid" , DC_BARE },
+ {"prefx" , DC_PREF_IDX },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"alnv.ps" , DC_FD_FS_FT_RS },
+ {"invalid" , DC_BARE },
+ {"madd.s" , DC_FD_FR_FS_FT },
+ {"madd.d" , DC_FD_FR_FS_FT },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"madd.ps" , DC_FD_FR_FS_FT },
+ {"invalid" , DC_BARE },
+ {"msub.s" , DC_FD_FR_FS_FT },
+ {"msub.d" , DC_FD_FR_FS_FT },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"msub.ps" , DC_FD_FR_FS_FT },
+ {"invalid" , DC_BARE },
+ {"nmadd.s" , DC_FD_FR_FS_FT },
+ {"nmadd.d" , DC_FD_FR_FS_FT },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"nmadd.ps" , DC_FD_FR_FS_FT },
+ {"invalid" , DC_BARE },
+ {"nmsub.s" , DC_FD_FR_FS_FT },
+ {"nmsub.d" , DC_FD_FR_FS_FT },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"invalid" , DC_BARE },
+ {"nmsub.ps" , DC_FD_FR_FS_FT },
+ {"invalid" , DC_BARE }};
+
+static const disasm_t disasm_mdmx[8] DATASEG =
+{{ "$20" , DC_DEREF },
+ { "$19" , DC_DEREF },
+ { "$20" , DC_DEREF },
+ { "$33" , DC_DEREF },
+ { "$20" , DC_DEREF },
+ { "$19" , DC_DEREF },
+ { "$20" , DC_DEREF },
+ { "$33" , DC_DEREF },
+};
+
+static const disasm_t disasm_mdmx_qh[64] DATASEG =
+{{ "msgn.qh" , DC_VD_VS_VT_VEC},
+ { "c.eq.qh" , DC_VS_VT_VEC },
+ { "pickf.qh" , DC_VD_VS_VT_VEC},
+ { "pickt.qh" , DC_VD_VS_VT_VEC},
+ { "c.lt.qh" , DC_VS_VT_VEC },
+ { "c.le.qh" , DC_VS_VT_VEC },
+ { "min.qh" , DC_VD_VS_VT_VEC},
+ { "max.qh" , DC_VD_VS_VT_VEC},
+
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "sub.qh" , DC_VD_VS_VT_VEC},
+ { "add.qh" , DC_VD_VS_VT_VEC},
+ { "and.qh" , DC_VD_VS_VT_VEC},
+ { "xor.qh" , DC_VD_VS_VT_VEC},
+ { "or.qh" , DC_VD_VS_VT_VEC},
+ { "nor.qh" , DC_VD_VS_VT_VEC},
+
+ { "sll.qh" , DC_VD_VS_VT_VEC},
+ { "invalid" , DC_BARE },
+ { "srl.qh" , DC_VD_VS_VT_VEC},
+ { "sra.qh" , DC_VD_VS_VT_VEC},
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+
+ { "alni.ob" , DC_VD_VS_VT_IMM},
+ { "alnv.ob" , DC_VD_VS_VT_RS },
+ { "alni.qh" , DC_VD_VS_VT_IMM},
+ { "alnv.qh" , DC_VD_VS_VT_RS },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "$34" , DC_DEREF },
+
+ { "rzu.qh" , DC_VD_VT },
+ { "rnau.qh" , DC_VD_VT },
+ { "rneu.qh" , DC_VD_VT },
+ { "invalid" , DC_BARE },
+ { "rzs.qh" , DC_VD_VT },
+ { "rnas.qh" , DC_VD_VT },
+ { "rnes.qh" , DC_VD_VT },
+ { "invalid" , DC_BARE },
+
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+
+ { "mul.qh" , DC_VD_VS_VT_VEC},
+ { "invalid" , DC_BARE },
+ { "$21" , DC_DEREF },
+ { "$22" , DC_DEREF },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "$23" , DC_DEREF },
+ { "$24" , DC_DEREF },
+
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "$25" , DC_DEREF },
+ { "$26" , DC_DEREF },
+};
+
+static const disasm_t disasm_mdmx_ob[64] DATASEG =
+{{ "invalid" , DC_BARE },
+ { "c.eq.ob" , DC_VS_VT_VEC },
+ { "pickf.ob" , DC_VD_VS_VT_VEC},
+ { "pickt.ob" , DC_VD_VS_VT_VEC},
+ { "c.lt.ob" , DC_VS_VT_VEC },
+ { "c.le.ob" , DC_VS_VT_VEC },
+ { "min.ob" , DC_VD_VS_VT_VEC},
+ { "max.ob" , DC_VD_VS_VT_VEC},
+
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "sub.ob" , DC_VD_VS_VT_VEC},
+ { "add.ob" , DC_VD_VS_VT_VEC},
+ { "and.ob" , DC_VD_VS_VT_VEC},
+ { "xor.ob" , DC_VD_VS_VT_VEC},
+ { "or.ob" , DC_VD_VS_VT_VEC},
+ { "nor.ob" , DC_VD_VS_VT_VEC},
+
+ { "sll.ob" , DC_VD_VS_VT_VEC},
+ { "invalid" , DC_BARE },
+ { "srl.ob" , DC_VD_VS_VT_VEC},
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+
+ { "alni.ob" , DC_VD_VS_VT_IMM},
+ { "alnv.ob" , DC_VD_VS_VT_RS },
+ { "alni.qh" , DC_VD_VS_VT_IMM},
+ { "alnv.qh" , DC_VD_VS_VT_RS },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "$35" , DC_DEREF },
+
+ { "rzu.ob" , DC_VD_VT },
+ { "rnau.ob" , DC_VD_VT },
+ { "rneu.ob" , DC_VD_VT },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+
+ { "mul.ob" , DC_VD_VS_VT_VEC},
+ { "invalid" , DC_BARE },
+ { "$27" , DC_DEREF },
+ { "$28" , DC_DEREF },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "$29" , DC_DEREF },
+ { "$30" , DC_DEREF },
+
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "$31" , DC_DEREF },
+ { "$32" , DC_DEREF },
+};
+
+static const disasm_t disasm_mdmx_alni[64] DATASEG =
+{{ "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+
+ { "alni.ob" , DC_VD_VS_VT_IMM},
+ { "alnv.ob" , DC_VD_VS_VT_RS },
+ { "alni.qh" , DC_VD_VS_VT_IMM},
+ { "alnv.qh" , DC_VD_VS_VT_RS },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+};
+
+static const disasm_t disasm_mdmx_muls_qh[2] DATASEG =
+{{ "muls.qh" , DC_VS_VT_VEC },
+ { "mulsl.qh" , DC_VS_VT_VEC },
+};
+
+static const disasm_t disasm_mdmx_mul_qh[2] DATASEG =
+{{ "mula.qh" , DC_VS_VT_VEC },
+ { "mull.qh" , DC_VS_VT_VEC },
+};
+
+static const disasm_t disasm_mdmx_sub_qh[2] DATASEG =
+{{ "suba.qh" , DC_VS_VT_VEC },
+ { "subl.qh" , DC_VS_VT_VEC },
+};
+
+static const disasm_t disasm_mdmx_add_qh[2] DATASEG =
+{{ "adda.qh" , DC_VS_VT_VEC },
+ { "addl.qh" , DC_VS_VT_VEC },
+};
+
+static const disasm_t disasm_mdmx_wac_qh[4] DATASEG =
+{{ "wacl.qh" , DC_VS_VT },
+ { "invalid" , DC_BARE },
+ { "wach.qh" , DC_VS },
+ { "invalid" , DC_BARE },
+};
+
+static const disasm_t disasm_mdmx_rac_qh[4] DATASEG =
+{{ "racl.qh" , DC_VD },
+ { "racm.qh" , DC_VD },
+ { "rach.qh" , DC_VD },
+ { "invalid" , DC_BARE },
+};
+
+static const disasm_t disasm_mdmx_muls_ob[2] DATASEG =
+{{ "muls.ob" , DC_VS_VT_VEC },
+ { "mulsl.ob" , DC_VS_VT_VEC },
+};
+
+static const disasm_t disasm_mdmx_mul_ob[2] DATASEG =
+{{ "mula.ob" , DC_VS_VT_VEC },
+ { "mull.ob" , DC_VS_VT_VEC },
+};
+
+static const disasm_t disasm_mdmx_sub_ob[2] DATASEG =
+{{ "suba.ob" , DC_VS_VT_VEC },
+ { "subl.ob" , DC_VS_VT_VEC },
+};
+
+static const disasm_t disasm_mdmx_add_ob[2] DATASEG =
+{{ "adda.ob" , DC_VS_VT_VEC },
+ { "addl.ob" , DC_VS_VT_VEC },
+};
+
+static const disasm_t disasm_mdmx_wac_ob[4] DATASEG =
+{{ "wacl.ob" , DC_VS_VT },
+ { "invalid" , DC_BARE },
+ { "wach.ob" , DC_VS },
+ { "invalid" , DC_BARE },
+};
+
+static const disasm_t disasm_mdmx_rac_ob[4] DATASEG =
+{{ "racl.ob" , DC_VD },
+ { "racm.ob" , DC_VD },
+ { "rach.ob" , DC_VD },
+ { "invalid" , DC_BARE },
+};
+
+static const disasm_t disasm_mdmx_shfl_ob[16] DATASEG =
+{{ "shfl.upsl.ob" , DC_VD_VS_VT },
+ { "shfl.pach.ob" , DC_VD_VS_VT },
+ { "shfl.mixh.ob" , DC_VD_VS_VT },
+ { "shfl.mixl.ob" , DC_VD_VS_VT },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+};
+
+static const disasm_t disasm_mdmx_shfl_qh[8] DATASEG =
+{{ "shfl.bfla.qh" , DC_VD_VS_VT },
+ { "shfl.pach.qh" , DC_VD_VS_VT },
+ { "shfl.mixh.qh" , DC_VD_VS_VT },
+ { "shfl.mixl.qh" , DC_VD_VS_VT },
+ { "shfl.repa.qh" , DC_VD_VS_VT },
+ { "shfl.repb.qh" , DC_VD_VS_VT },
+ { "invalid" , DC_BARE },
+ { "invalid" , DC_BARE },
+};
+
+
+
+const disasm_deref_t disasm_deref[] =
+/* Disasm array shft msk */
+{{ disasm_normal , 26, 0x3f }, /* 0 */
+ { disasm_special , 0, 0x3f }, /* 1 */
+ { disasm_regimm , 16, 0x1f }, /* 2 */
+ { disasm_spec2 , 0, 0x3f }, /* 3 */
+ { disasm_cop0 , 21, 0x1f }, /* 4 */
+ { disasm_cop0_c0 , 0, 0x3f }, /* 5 */
+ { disasm_cop1 , 21, 0x1f }, /* 6 */
+ { disasm_cop1_s , 0, 0x3f }, /* 7 */
+ { disasm_cop1_s_mvcf , 16, 0x1 }, /* 8 */
+ { disasm_cop1_d , 0, 0x3f }, /* 9 */
+ { disasm_cop1_d_mvcf , 16, 0x1 }, /* 10 */
+ { disasm_cop1_w , 0, 0x3f }, /* 11 */
+ { disasm_cop1_l , 0, 0x3f }, /* 12 */
+ { disasm_cop1_ps , 0, 0x3f }, /* 13 */
+ { disasm_cop1_ps_mvcf, 16, 0x1 }, /* 14 */
+ { disasm_cop1x , 0, 0x3f }, /* 15 */
+ { disasm_movci , 16, 0x1 }, /* 16 */
+ { disasm_cop1_bc1 , 16, 0x3 }, /* 17 */
+ { disasm_mdmx , 21, 0x7 }, /* 18 */
+ { disasm_mdmx_qh , 0, 0x3f }, /* 19 */
+ { disasm_mdmx_ob , 0, 0x3f }, /* 20 */
+ { disasm_mdmx_muls_qh, 10, 0x1 }, /* 21 */
+ { disasm_mdmx_mul_qh , 10, 0x1 }, /* 22 */
+ { disasm_mdmx_sub_qh , 10, 0x1 }, /* 23 */
+ { disasm_mdmx_add_qh , 10, 0x1 }, /* 24 */
+ { disasm_mdmx_wac_qh , 24, 0x3 }, /* 25 */
+ { disasm_mdmx_rac_qh , 24, 0x3 }, /* 26 */
+ { disasm_mdmx_muls_ob, 10, 0x1 }, /* 27 */
+ { disasm_mdmx_mul_ob , 10, 0x1 }, /* 28 */
+ { disasm_mdmx_sub_ob , 10, 0x1 }, /* 29 */
+ { disasm_mdmx_add_ob , 10, 0x1 }, /* 30 */
+ { disasm_mdmx_wac_ob , 24, 0x3 }, /* 31 */
+ { disasm_mdmx_rac_ob , 24, 0x3 }, /* 32 */
+ { disasm_mdmx_alni , 0, 0x3f }, /* 33 */
+ { disasm_mdmx_shfl_ob, 22, 0xf }, /* 34 */
+ { disasm_mdmx_shfl_qh, 23, 0x7 }, /* 35 */
+ { disasm_cop1_bc1any2, 16, 0x1 }, /* 36 */
+ { disasm_cop1_bc1any4, 16, 0x1 }, /* 37 */
+ { disasm_cop1_c_f_s , 6, 0x1 }, /* 38 */
+ { disasm_cop1_c_un_s , 6, 0x1 }, /* 39 */
+ { disasm_cop1_c_eq_s , 6, 0x1 }, /* 40 */
+ { disasm_cop1_c_ueq_s, 6, 0x1 }, /* 41 */
+ { disasm_cop1_c_olt_s, 6, 0x1 }, /* 42 */
+ { disasm_cop1_c_ult_s, 6, 0x1 }, /* 43 */
+ { disasm_cop1_c_ole_s, 6, 0x1 }, /* 44 */
+ { disasm_cop1_c_ule_s, 6, 0x1 }, /* 45 */
+ { disasm_cop1_c_sf_s , 6, 0x1 }, /* 46 */
+ { disasm_cop1_c_ngle_s, 6, 0x1 }, /* 47 */
+ { disasm_cop1_c_seq_s, 6, 0x1 }, /* 48 */
+ { disasm_cop1_c_ngl_s, 6, 0x1 }, /* 49 */
+ { disasm_cop1_c_lt_s , 6, 0x1 }, /* 50 */
+ { disasm_cop1_c_nge_s, 6, 0x1 }, /* 51 */
+ { disasm_cop1_c_le_s , 6, 0x1 }, /* 52 */
+ { disasm_cop1_c_ngt_s, 6, 0x1 }, /* 53 */
+ { disasm_cop1_c_f_d , 6, 0x1 }, /* 54 */
+ { disasm_cop1_c_un_d , 6, 0x1 }, /* 55 */
+ { disasm_cop1_c_eq_d , 6, 0x1 }, /* 56 */
+ { disasm_cop1_c_ueq_d, 6, 0x1 }, /* 57 */
+ { disasm_cop1_c_olt_d, 6, 0x1 }, /* 58 */
+ { disasm_cop1_c_ult_d, 6, 0x1 }, /* 59 */
+ { disasm_cop1_c_ole_d, 6, 0x1 }, /* 60 */
+ { disasm_cop1_c_ule_d, 6, 0x1 }, /* 61 */
+ { disasm_cop1_c_sf_d , 6, 0x1 }, /* 62 */
+ { disasm_cop1_c_ngle_d, 6, 0x1 }, /* 63 */
+ { disasm_cop1_c_seq_d, 6, 0x1 }, /* 64 */
+ { disasm_cop1_c_ngl_d, 6, 0x1 }, /* 65 */
+ { disasm_cop1_c_lt_d , 6, 0x1 }, /* 66 */
+ { disasm_cop1_c_nge_d, 6, 0x1 }, /* 67 */
+ { disasm_cop1_c_le_d , 6, 0x1 }, /* 68 */
+ { disasm_cop1_c_ngt_d, 6, 0x1 }, /* 69 */
+ { disasm_cop1_c_f_ps , 6, 0x1 }, /* 70 */
+ { disasm_cop1_c_un_ps, 6, 0x1 }, /* 71 */
+ { disasm_cop1_c_eq_ps, 6, 0x1 }, /* 72 */
+ { disasm_cop1_c_ueq_ps, 6, 0x1 }, /* 73 */
+ { disasm_cop1_c_olt_ps, 6, 0x1 }, /* 74 */
+ { disasm_cop1_c_ult_ps, 6, 0x1 }, /* 75 */
+ { disasm_cop1_c_ole_ps, 6, 0x1 }, /* 76 */
+ { disasm_cop1_c_ule_ps, 6, 0x1 }, /* 77 */
+ { disasm_cop1_c_sf_ps, 6, 0x1 }, /* 78 */
+ { disasm_cop1_c_ngle_ps, 6, 0x1 }, /* 79 */
+ { disasm_cop1_c_seq_ps, 6, 0x1 }, /* 80 */
+ { disasm_cop1_c_ngl_ps, 6, 0x1 }, /* 81 */
+ { disasm_cop1_c_lt_ps, 6, 0x1 }, /* 82 */
+ { disasm_cop1_c_nge_ps, 6, 0x1 }, /* 83 */
+ { disasm_cop1_c_le_ps, 6, 0x1 }, /* 84 */
+ { disasm_cop1_c_ngt_ps, 6, 0x1 }, /* 85 */
+};
+
+#define PREFHINT(x) (&pref_hints[(x)*9])
+static char *pref_hints =
+ "load \0"
+ "store \0"
+ "reserved\0"
+ "reserved\0"
+
+ "ld_strm \0"
+ "st_strm \0"
+ "ld_retn \0"
+ "st_retn \0"
+
+ "reserved\0"
+ "reserved\0"
+ "reserved\0"
+ "reserved\0"
+
+ "reserved\0"
+ "reserved\0"
+ "reserved\0"
+ "reserved\0"
+
+ "reserved\0"
+ "reserved\0"
+ "reserved\0"
+ "reserved\0"
+
+ "reserved\0"
+ "reserved\0"
+ "reserved\0"
+ "reserved\0"
+
+ "reserved\0"
+ "wb_inval\0"
+ "reserved\0"
+ "reserved\0"
+
+ "reserved\0"
+ "reserved\0"
+ "reserved\0"
+ "reserved\0";
+
+
+static int snprintf(char *buf,int len,const char *templat,...)
+{
+ va_list marker;
+ int count;
+
+ va_start(marker,templat);
+ count = xvsprintf(buf,templat,marker);
+ va_end(marker);
+
+ return count;
+}
+
+static const disasm_t *get_disasm_field(uint32_t inst)
+{
+ const disasm_deref_t *tmp = &disasm_deref[0];
+ const disasm_t *rec;
+ do {
+ rec = &(tmp->ptr[(inst>>tmp->shift) & tmp->mask]);
+ tmp = &disasm_deref[atoi(&(rec->name[1]))];
+ } while (rec->type == DC_DEREF);
+ return rec;
+}
+
+char *disasm_inst_name(uint32_t inst)
+{
+ return (char *)(get_disasm_field(inst)->name);
+}
+
+void disasm_inst(char *buf, int buf_size, uint32_t inst, uint64_t pc)
+{
+ const disasm_t *tmp;
+ char instname[32];
+ int commentmode = 0;
+ char *x;
+
+ tmp = get_disasm_field(inst);
+
+ strcpy(instname,(char *) tmp->name);
+
+ if ((x = strchr(instname,'@'))) {
+ *x++ = 0;
+ commentmode = atoi(x);
+ }
+
+ switch (tmp->type) {
+ case DC_RD_RS_RT:
+ snprintf(buf, buf_size, "%-8s %s,%s,%s",
+ instname,
+ REGNAME((inst>>11) & 0x1f),
+ REGNAME((inst>>21) & 0x1f),
+ REGNAME((inst>>16) & 0x1f));
+ break;
+ case DC_RD_RT_RS:
+ snprintf(buf, buf_size, "%-8s %s,%s,%s",
+ instname,
+ REGNAME((inst>>11) & 0x1f),
+ REGNAME((inst>>16) & 0x1f),
+ REGNAME((inst>>21) & 0x1f));
+ break;
+ case DC_RT_RS_SIMM:
+ snprintf(buf, buf_size, "%-8s %s,%s,#%" PF_32 "d",
+ instname,
+ REGNAME((inst>>16) & 0x1f),
+ REGNAME((inst>>21) & 0x1f),
+ SEXT_32(15, inst & 0xffff));
+ break;
+ case DC_RT_RS_XIMM:
+ snprintf(buf, buf_size, "%-8s %s,%s,#0x%" PF_32 "x",
+ instname,
+ REGNAME((inst>>16) & 0x1f),
+ REGNAME((inst>>21) & 0x1f),
+ inst & 0xffff);
+ break;
+ case DC_RS_RT_OFS:
+ snprintf(buf, buf_size, "%-8s %s,%s,0x%" PF_64 "x",
+ instname,
+ REGNAME((inst>>21) & 0x1f),
+ REGNAME((inst>>16) & 0x1f),
+ pc + 4 + (SEXT_64(15, inst & 0xffff)<<2));
+ break;
+ case DC_RS_OFS:
+ snprintf(buf, buf_size, "%-8s %s,0x%" PF_64 "x",
+ instname,
+ REGNAME((inst>>21) & 0x1f),
+ pc + 4 + (SEXT_64(16, inst & 0xffff)<<2));
+ break;
+ case DC_RD_RT_SA:
+ snprintf(buf, buf_size, "%-8s %s,%s,#%d",
+ instname,
+ REGNAME((inst>>11) & 0x1f),
+ REGNAME((inst>>16) & 0x1f),
+ (inst>>6) & 0x1f);
+ break;
+ case DC_RT_UIMM:
+ snprintf(buf, buf_size, "%-8s %s,#%d",
+ instname,
+ REGNAME((inst>>16) & 0x1f),
+ inst & 0xffff);
+ break;
+ case DC_RD:
+ snprintf(buf, buf_size, "%-8s %s",
+ instname,
+ REGNAME((inst>>11) & 0x1f));
+ break;
+ case DC_J:
+ snprintf(buf, buf_size, "%-8s 0x%" PF_64 "x",
+ instname,
+ (pc & UINT64_T(0xfffffffff0000000)) | ((inst & 0x3ffffff)<<2));
+ break;
+ case DC_RD_RS:
+ snprintf(buf, buf_size, "%-8s %s,%s",
+ instname,
+ REGNAME((inst>>11) & 0x1f),
+ REGNAME((inst>>21) & 0x1f));
+ break;
+ case DC_RS_RT:
+ snprintf(buf, buf_size, "%-8s %s,%s",
+ instname,
+ REGNAME((inst>>21) & 0x1f),
+ REGNAME((inst>>16) & 0x1f));
+ break;
+ case DC_RT_RS:
+ snprintf(buf, buf_size, "%-8s %s,%s",
+ instname,
+ REGNAME((inst>>16) & 0x1f),
+ REGNAME((inst>>21) & 0x1f));
+ break;
+ case DC_RT_RD_SEL:
+ snprintf(buf, buf_size, "%-8s %s,%s,#%d",
+ instname,
+ REGNAME((inst>>16) & 0x1f),
+ REGNAME((inst>>11) & 0x1f),
+ inst & 0x3);
+ break;
+ case DC_RT_CR_SEL:
+ snprintf(buf, buf_size, "%-8s %s,%d,#%d",
+ instname,
+ REGNAME((inst>>16) & 0x1f),
+ (inst>>11) & 0x1f,
+ inst & 0x3);
+ break;
+ case DC_RS:
+ snprintf(buf, buf_size, "%-8s %s",
+ instname,
+ REGNAME((inst>>21) & 0x1f));
+ break;
+ case DC_RS_SIMM:
+ snprintf(buf, buf_size, "%-8s %s,#%" PF_32 "d",
+ instname,
+ REGNAME((inst>>21) & 0x1f),
+ SEXT_32(15, inst & 0xffff));
+ break;
+ case DC_RT_OFS_BASE:
+ snprintf(buf, buf_size, "%-8s %s,#%" PF_32 "d(%s)",
+ instname,
+ REGNAME((inst>>16) & 0x1f),
+ SEXT_32(15, inst),
+ REGNAME((inst>>21) & 0x1f));
+ break;
+ case DC_FT_OFS_BASE:
+ snprintf(buf, buf_size, "%-8s f%d,#%" PF_32 "d(%s)",
+ instname,
+ (inst>>16) & 0x1f,
+ SEXT_32(15, inst),
+ REGNAME((inst>>21) & 0x1f));
+ break;
+ case DC_FD_IDX_BASE:
+ snprintf(buf, buf_size, "%-8s f%d,%s(%s)",
+ instname,
+ (inst>>6) & 0x1f,
+ REGNAME((inst>>16) & 0x1f),
+ REGNAME((inst>>21) & 0x1f));
+ break;
+ case DC_FS_IDX_BASE:
+ snprintf(buf, buf_size, "%-8s f%d,%s(%s)",
+ instname,
+ (inst>>11) & 0x1f,
+ REGNAME((inst>>16) & 0x1f),
+ REGNAME((inst>>21) & 0x1f));
+ break;
+ case DC_FD_FS_FT:
+ snprintf(buf, buf_size, "%-8s f%d,f%d,f%d",
+ instname,
+ (inst>>6) & 0x1f,
+ (inst>>11) & 0x1f,
+ (inst>>16) & 0x1f);
+ break;
+ case DC_FD_FS_RT:
+ snprintf(buf, buf_size, "%-8s f%d,f%d,%s",
+ instname,
+ (inst>>6) & 0x1f,
+ (inst>>11) & 0x1f,
+ REGNAME((inst>>16) & 0x1f));
+ break;
+ case DC_FD_FS:
+ snprintf(buf, buf_size, "%-8s f%d,f%d",
+ instname,
+ (inst>>6)&0x1f,
+ (inst>>11)&0x1f);
+ break;
+ case DC_PREF_OFS:
+ snprintf(buf, buf_size, "%-8s #%" PF_32 "d(%s) /* %s */",
+ instname,
+ SEXT_32(15, inst & 0xffff),
+ REGNAME((inst>>21) & 0x1f),
+ PREFHINT((inst>>16) & 0x1f));
+ break;
+ case DC_PREF_IDX:
+ snprintf(buf, buf_size, "%-8s %s(%s) /* %s */",
+ instname,
+ REGNAME((inst>>16) & 0x1f),
+ REGNAME((inst>>21) & 0x1f),
+ PREFHINT((inst>>16) & 0x1f));
+ break;
+ case DC_CC_OFS:
+ snprintf(buf, buf_size, "%-8s %d,0x%" PF_64 "x",
+ instname,
+ (inst>>18) & 0x7,
+ pc + 4 + (SEXT_64(15, inst & 0xffff)<<2));
+ break;
+ case DC_RD_RS_CC:
+ snprintf(buf, buf_size, "%-8s %s,%s,%d",
+ instname,
+ REGNAME((inst>>11) & 0x1f),
+ REGNAME((inst>>21) & 0x1f),
+ (inst>>18) & 0x7);
+ break;
+ case DC_FD_FS_CC:
+ snprintf(buf, buf_size, "%-8s f%d,f%d,%d",
+ instname,
+ (inst>>6) & 0x1f,
+ (inst>>11) & 0x1f,
+ (inst>>18) & 0x7);
+ break;
+ case DC_FD_FR_FS_FT:
+ snprintf(buf, buf_size, "%-8s f%d,f%d,f%d,f%d",
+ instname,
+ (inst>>6) & 0x1f,
+ (inst>>21) & 0x1f,
+ (inst>>11) & 0x1f,
+ (inst>>16) & 0x1f);
+ break;
+ case DC_FD_FS_FT_RS:
+ snprintf(buf, buf_size, "%-8s f%d,f%d,f%d,%s",
+ instname,
+ (inst>>6) & 0x1f,
+ (inst>>11) & 0x1f,
+ (inst>>16) & 0x1f,
+ REGNAME((inst>>21) & 0x1f));
+ break;
+ case DC_CC_FS_FT:
+ snprintf(buf, buf_size, "%-8s %d,f%d,f%d",
+ instname,
+ (inst>>8) & 0x7,
+ (inst>>11) & 0x1f,
+ (inst>>16) & 0x1f);
+ break;
+ case DC_BARE:
+ snprintf(buf, buf_size, "%-8s", instname);
+ break;
+ case DC_RT_FS:
+ snprintf(buf, buf_size, "%-8s %s,f%d",
+ instname,
+ REGNAME((inst>>16) & 0x1f),
+ (inst>>11) & 0x1f);
+ break;
+ case DC_VS:
+ snprintf(buf, buf_size, "%-8s $v%d",
+ instname,
+ (inst>>11) & 0x1f);
+ break;
+ case DC_VD:
+ snprintf(buf, buf_size, "%-8s $v%d",
+ instname,
+ (inst>>6) & 0x1f);
+ break;
+ case DC_VD_VT:
+ snprintf(buf, buf_size, "%-8s $v%d,$v%d",
+ instname,
+ (inst>>6) & 0x1f,
+ (inst>>16) & 0x1f);
+ break;
+ case DC_VD_VS_VT_IMM:
+ snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d,#%d",
+ instname,
+ (inst>>6) & 0x1f,
+ (inst>>11) & 0x1f,
+ (inst>>16) & 0x1f,
+ (inst>>21) & 0x7);
+ break;
+ case DC_VD_VS_VT_RS:
+ snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d,%s",
+ instname,
+ (inst>>6) & 0x1f,
+ (inst>>11) & 0x1f,
+ (inst>>16) & 0x1f,
+ REGNAME((inst>>21) & 0x1f));
+ break;
+ case DC_VD_VS_VT:
+ snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d",
+ instname,
+ (inst>>6) & 0x1f,
+ (inst>>11) & 0x1f,
+ (inst>>16) & 0x1f);
+ break;
+ case DC_VS_VT:
+ snprintf(buf, buf_size, "%-8s $v%d,$v%d",
+ instname,
+ (inst>>11) & 0x1f,
+ (inst>>16) & 0x1f);
+ break;
+ case DC_VS_VT_VEC:
+ switch((inst>>24) & 0x3) {
+ case 0:
+ case 1:
+ /* element select */
+ if ((inst>>21) & 1) {
+ /* QH */
+ snprintf(buf, buf_size, "%-8s $v%d,$v%d[%d]",
+ instname,
+ (inst>>11) & 0x1f,
+ (inst>>16) & 0x1f,
+ (inst>>23) & 0x3);
+ } else {
+ /* OB */
+ snprintf(buf, buf_size, "%-8s $v%d,$v%d[%d]",
+ instname,
+ (inst>>11) & 0x1f,
+ (inst>>16) & 0x1f,
+ (inst>>22) & 0x7);
+
+ }
+ break;
+ case 2:
+ /* Vector select */
+ snprintf(buf, buf_size, "%-8s $v%d,$v%d",
+ instname,
+ (inst>>11) & 0x1f,
+ (inst>>16) & 0x1f);
+ break;
+ case 3:
+ /* immediate select */
+ snprintf(buf, buf_size, "%-8s $v%d,$#%d",
+ instname,
+ (inst>>11) & 0x1f,
+ (inst>>16) & 0x1f);
+ break;
+ }
+ break;
+
+ case DC_VD_VS_VT_VEC:
+ switch((inst>>24) & 0x3) {
+ case 0:
+ case 1:
+ /* element select */
+ if ((inst>>21) & 1) {
+ /* QH */
+ snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d[%d]",
+ instname,
+ (inst>>6) & 0x1f,
+ (inst>>11) & 0x1f,
+ (inst>>16) & 0x1f,
+ (inst>>23) & 0x3);
+ } else {
+ /* OB */
+ snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d[%d]",
+ instname,
+ (inst>>6) & 0x1f,
+ (inst>>11) & 0x1f,
+ (inst>>16) & 0x1f,
+ (inst>>22) & 0x7);
+
+ }
+ break;
+ case 2:
+ /* Vector select */
+ snprintf(buf, buf_size, "%-8s $v%d,$v%d,$v%d",
+ instname,
+ (inst>>6) & 0x1f,
+ (inst>>11) & 0x1f,
+ (inst>>16) & 0x1f);
+ break;
+ case 3:
+ /* immediate select */
+ snprintf(buf, buf_size, "%-8s $v%d,$v%d,$#%d",
+ instname,
+ (inst>>6) & 0x1f,
+ (inst>>11) & 0x1f,
+ (inst>>16) & 0x1f);
+ break;
+ }
+ break;
+
+ case DC_SYSCALL:
+ snprintf(buf, buf_size, "%-8s #%d",
+ instname,
+ (inst>>6) & 0xfffff);
+ break;
+ case DC_BREAK:
+ snprintf(buf, buf_size, "%-8s %d", instname, (inst>>6)&0xfffff);
+ break;
+ case DC_OOPS:
+ snprintf(buf, buf_size, "%s OOPS! FIXME!", instname);
+ break;
+ default:
+ /* Hit something we don't know about...Shouldn't happen. */
+ break;
+ }
+
+ /*
+ * Handle comment field
+ */
+
+
+ switch (commentmode) {
+ case 1: /* CP0 ops */
+ if ((inst & 3) == 0) { /* select 0 */
+ snprintf(buf + strlen(buf),buf_size-strlen(buf)," /* %s */",
+ CP0REGNAME((inst >> 11) & 0x1f));
+ }
+ break;
+ default:
+ break;
+ }
+
+ buf[buf_size-1] = 0;
+
+}
diff --git a/cfe/cfe/arch/mips/common/src/exception.S b/cfe/cfe/arch/mips/common/src/exception.S
new file mode 100644
index 0000000..8036b35
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/exception.S
@@ -0,0 +1,546 @@
+/* *********************************************************************
+ * SB1250 Board Support Package
+ *
+ * Exception Handler File: exception.S
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "sbmips.h"
+#include "exception.h"
+#include "mipsmacros.h"
+#include "cpu_config.h" /* for definition of HAZARD and ERET */
+#include "bsp_config.h"
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#ifdef _MIPSREGS32_
+#define LREG lw
+#define SREG sw
+#define SRL srl
+#define SLL sll
+#else
+#define LREG ld
+#define SREG sd
+#define SRL dsrl
+#define SLL dsll
+#endif
+
+
+/* *********************************************************************
+ * Data
+ ********************************************************************* */
+
+ .sdata
+
+ .globl _exc_vectab
+_exc_vectab: _LONG_ 0 # XTYPE_RESET
+ _LONG_ 0 # XTYPE_TLBFILL (not used)
+ _LONG_ 0 # XTYPE_XTLBFILL
+ _LONG_ 0 # XTYPE_CACHEERR (not used)
+ _LONG_ 0 # XTYPE_EXCEPTION
+ _LONG_ 0 # XTYPE_INTERRUPT
+ _LONG_ 0 # XTYPE_EJTAG
+
+/* *********************************************************************
+ * Common Data
+ ********************************************************************* */
+
+ .bss
+
+
+/* *********************************************************************
+ * Code
+ ********************************************************************* */
+
+ .text
+
+#define R_EXC_CERR_TEMPLATE _TBLIDX(0)
+#define R_EXC_CERR_TEMPLATE_END _TBLIDX(1)
+
+ .globl _exc_cerr_htable
+_exc_cerr_htable:
+ _LONG_ _exc_cerr_template
+ _LONG_ _exc_cerr_template_end
+
+
+/* *********************************************************************
+ * _exc_cerr_template
+ *
+ * This is a template routine for our cache error handler.
+ * We save a couple of registers in our magic save area, then
+ * dispatch to code elsewhere in CFE.
+ *
+ * This code is copied right to the vector address, so it has
+ * to be kept tiny!
+ *
+ * Input parameters:
+ * nothing - running uncached, all registers trashed
+ *
+ * Return value:
+ * might return, might not
+ ********************************************************************* */
+
+LEAF(_exc_cerr_template)
+
+ /*
+ * Magic! When the cache error handler is running,
+ * we are in a very special state, running uncached
+ * and with translations turned off. We can use offsets
+ * from r0(zero) to store registers we need to use
+ * during the error handler.
+ */
+
+ .set push ; .set noreorder
+
+ SR k0,CFE_LOCORE_GLOBAL_K0TMP(zero)
+ SR k1,CFE_LOCORE_GLOBAL_K1TMP(zero)
+ SR ra,CFE_LOCORE_GLOBAL_RATMP(zero)
+ SR gp,CFE_LOCORE_GLOBAL_GPTMP(zero)
+
+ LR k0,CFE_LOCORE_GLOBAL_CERRH(zero)
+ jal k0
+ nop
+
+ LR k0,CFE_LOCORE_GLOBAL_K0TMP(zero)
+ LR k1,CFE_LOCORE_GLOBAL_K1TMP(zero)
+ LR ra,CFE_LOCORE_GLOBAL_RATMP(zero)
+ LR gp,CFE_LOCORE_GLOBAL_GPTMP(zero)
+ ERET
+
+ .set pop
+
+ /*
+ * Note: make sure this routine does not exceed 128 bytes
+ */
+
+_exc_cerr_template_end:
+
+END(_exc_cerr_template)
+
+/* *********************************************************************
+ * _exc_setup_locore(cerrh)
+ *
+ * Set global data into the low-memory region. We do this in
+ * assembly language so it's easier to deal with the 32-bit/64-bit
+ * issues that arise in the "C" code.
+ *
+ * Input parameters:
+ * a0 - cache error handler
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(_exc_setup_locore)
+
+ move t4,ra
+
+ /*
+ * Save GP for easy re-use, using uncached writes.
+ */
+
+ li t0,PHYS_TO_K1(CFE_LOCORE_GLOBAL_GP)
+ SR gp,0(t0)
+
+ /*
+ * Initialize cache error handler pointer. Make it
+ * uncached, since cache error handlers should not
+ * touch the cache.
+ */
+
+ li t1,(K0SIZE-1)
+ and a0,a0,t1 # keep just physical part
+ li t1,K1BASE
+ or a0,a0,t1 # make into an uncached address
+
+ li t0,PHYS_TO_K1(CFE_LOCORE_GLOBAL_CERRH)
+ SR a0,0(t0)
+
+ /*
+ * Move the cache error handler into low RAM.
+ */
+
+ li t0,PHYS_TO_K1(MIPS_RAM_VEC_CACHEERR)
+
+ LOADREL(t1,_exc_cerr_htable)
+ LR t2,R_EXC_CERR_TEMPLATE_END(t1)
+ LR t1,R_EXC_CERR_TEMPLATE(t1)
+
+1: lw t3,0(t1) # get a word
+ sw t3,0(t0) # write a word
+ ADD t0,4 # next word...
+ ADD t1,4
+ blt t1,t2,1b # till done
+
+ /*
+ * Now do the whole thing again, but with cached writes.
+ * Writing uncached makes sure the data is actually in memory,
+ * and writing cached makes sure we write the same
+ * stuff again when the cache is evicted.
+ * This way we don't have to bother with cacheops,
+ * a bonus on the BCM1250 with its funky L2.
+ */
+
+ li t0,PHYS_TO_K0(CFE_LOCORE_GLOBAL_GP)
+ SR gp,0(t0)
+
+ li t0,PHYS_TO_K0(CFE_LOCORE_GLOBAL_CERRH)
+ SR a0,0(t0)
+
+ li t0,PHYS_TO_K0(MIPS_RAM_VEC_CACHEERR)
+
+ LOADREL(t1,_exc_cerr_htable)
+ LR t2,R_EXC_CERR_TEMPLATE_END(t1)
+ LR t1,R_EXC_CERR_TEMPLATE(t1)
+
+1: lw t3,0(t1) # get a word
+ sw t3,0(t0) # write a word
+ ADD t0,4 # next word...
+ ADD t1,4
+ blt t1,t2,1b # till done
+
+
+ /*
+ * done!
+ */
+
+ move ra,t4
+ j ra
+
+END(_exc_setup_locore)
+
+
+
+
+/* *********************************************************************
+ * _exc_setvector(xtype,addr)
+ *
+ * Set an exception vector address
+ *
+ * Input parameters:
+ * xtype - exception vector type
+ * addr - routine address
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(_exc_setvector)
+
+ la v0,_exc_vectab
+ srl a0,3 /* convert 8-byte index to array index */
+ sll a0,BPWSIZE /* convert back to index appropriate for word size */
+ add v0,a0
+ SR a1,(v0)
+ j ra
+
+END(_exc_setvector)
+
+
+/* *********************************************************************
+ * _exc_crash_sim()
+ *
+ * Crash the GDB simulator, causing it to exit.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing - does not return
+ ********************************************************************* */
+
+
+LEAF(_exc_crash_sim)
+
+ li $2,1
+ li $3,0xdead
+ li $4,0
+ syscall 0xca
+1: b 1b
+
+END(_exc_crash_sim)
+
+
+/* *********************************************************************
+ * _exc_cache_crash_sim()
+ *
+ * As _exc_crash_sim, but distinguish cache error exception.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing - does not return
+ ********************************************************************* */
+
+
+LEAF(_exc_cache_crash_sim)
+
+ li $2,1
+ li $3,0xbadc
+ li $4,0
+ syscall 0xca
+1: b 1b
+
+END(_exc_cache_crash_sim)
+
+
+/* *********************************************************************
+ * _exc_restart()
+ *
+ * Restart the firmware at the boot address
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(_exc_restart)
+
+ li t0,0xBFC00000 # ROM restart vector
+ jr t0
+
+END(_exc_restart)
+
+/* *********************************************************************
+ * _exc_entry(k0)
+ *
+ * Main exception entry point.
+ *
+ * Input parameters:
+ * k0 - exception type
+ *
+ * Return value:
+ * ...
+ ********************************************************************* */
+
+LEAF(_exc_entry)
+
+ .set noreorder
+ .set noat
+
+ subu k1,sp,EXCEPTION_SIZE
+ SRL k1,3
+ SLL k1,3
+
+ SREG zero,XGR_ZERO(k1)
+ SREG AT,XGR_AT(k1)
+
+ SREG v0,XGR_V0(k1)
+ SREG v1,XGR_V1(k1)
+
+ SREG a0,XGR_A0(k1)
+ SREG a1,XGR_A1(k1)
+ SREG a2,XGR_A2(k1)
+ SREG a3,XGR_A3(k1)
+
+ SREG t0,XGR_T0(k1)
+ SREG t1,XGR_T1(k1)
+ SREG t2,XGR_T2(k1)
+ SREG t3,XGR_T3(k1)
+ SREG t4,XGR_T4(k1)
+ SREG t5,XGR_T5(k1)
+ SREG t6,XGR_T6(k1)
+ SREG t7,XGR_T7(k1)
+
+ SREG s0,XGR_S0(k1)
+ SREG s1,XGR_S1(k1)
+ SREG s2,XGR_S2(k1)
+ SREG s3,XGR_S3(k1)
+ SREG s4,XGR_S4(k1)
+ SREG s5,XGR_S5(k1)
+ SREG s6,XGR_S6(k1)
+ SREG s7,XGR_S7(k1)
+
+ SREG t8,XGR_T8(k1)
+ SREG t9,XGR_T9(k1)
+
+ SREG gp,XGR_GP(k1)
+ SREG sp,XGR_SP(k1)
+ SREG fp,XGR_FP(k1)
+ SREG ra,XGR_RA(k1)
+
+ mfc0 t0,C0_CAUSE
+ mfc0 t1,C0_SR
+ MFC0 t2,C0_BADVADDR
+ MFC0 t3,C0_EPC
+ mfc0 t4,C0_PRID
+ mflo t5
+ mfhi t6
+ SREG t0,XCP0_CAUSE(k1)
+ SREG t1,XCP0_SR(k1)
+ SREG t2,XCP0_VADDR(k1)
+ SREG t3,XCP0_EPC(k1)
+ SREG t4,XCP0_PRID(k1)
+ SREG t5,XGR_LO(k1)
+ SREG t6,XGR_HI(k1)
+
+#if CFG_EMBEDDED_PIC
+ la gp,PHYS_TO_K0(CFE_LOCORE_GLOBAL_GP)
+ LR gp,0(gp) # get our GP handle from low memory vector
+#else
+ la gp,_gp # Load up GP, not relocated so it's easy
+#endif
+
+ move a0,k0 # Pass exception type
+ move a1,k1 # Pass frame to exception handler
+ la t0,_exc_vectab # get base of exception vectors
+ srl k0,3 # convert 8-byte index to array index
+ sll k0,BPWSIZE # convert back to index appropriate for word size
+ addu t0,k0 # get vector address
+ LR t0,(t0) # to call handler
+
+ move sp,k1 # "C" gets fresh stack area
+
+ jalr t0 # Call exception handler
+ nop
+
+ move k1, sp
+ LREG AT,XGR_AT(k1)
+
+ LREG t0,XGR_LO(k1)
+ LREG t1,XGR_HI(k1)
+ mtlo t0
+ mthi t1
+
+ LREG a0,XGR_A0(k1)
+ LREG a1,XGR_A1(k1)
+ LREG a2,XGR_A2(k1)
+ LREG a3,XGR_A3(k1)
+
+ LREG t0,XGR_T0(k1)
+ LREG t1,XGR_T1(k1)
+ LREG t2,XGR_T2(k1)
+ LREG t3,XGR_T3(k1)
+ LREG t4,XGR_T4(k1)
+ LREG t5,XGR_T5(k1)
+ LREG t6,XGR_T6(k1)
+ LREG t7,XGR_T7(k1)
+
+ LREG s0,XGR_S0(k1)
+ LREG s1,XGR_S1(k1)
+ LREG s2,XGR_S2(k1)
+ LREG s3,XGR_S3(k1)
+ LREG s4,XGR_S4(k1)
+ LREG s5,XGR_S5(k1)
+ LREG s6,XGR_S6(k1)
+ LREG s7,XGR_S7(k1)
+
+ LREG t8,XGR_T8(k1)
+ LREG t9,XGR_T9(k1)
+
+ LREG gp,XGR_GP(k1)
+ LREG sp,XGR_SP(k1)
+ LREG fp,XGR_FP(k1)
+ LREG ra,XGR_RA(k1)
+
+/* do any CP0 cleanup here */
+
+ LREG v0,XGR_V0(k1)
+ LREG v1,XGR_V1(k1)
+
+ ERET
+
+ .set at
+ .set reorder
+
+
+END(_exc_entry)
+
+
+/* *********************************************************************
+ * _exc_clear_sr_exl()
+ *
+ * Clear SR(EXL) and return to caller.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(_exc_clear_sr_exl)
+
+ mfc0 t0,C0_SR
+ and t0,t0,~(0x02) # clear SR(EXL). Bit 1
+ mtc0 t0,C0_SR
+
+ HAZARD
+
+ j ra
+
+END(_exc_clear_sr_exl)
+
+/* *********************************************************************
+ * _exc_clear_sr_erl()
+ *
+ * Clear SR(ERL) and return to caller.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(_exc_clear_sr_erl)
+
+ mfc0 t0,C0_SR
+ and t0,t0,~(0x04) # clear SR(ERL). Bit 2
+ mtc0 t0,C0_SR
+
+ HAZARD
+
+ j ra
+
+END(_exc_clear_sr_erl)
+
+
+/* *********************************************************************
+ * End
+ ********************************************************************* */
+
+
diff --git a/cfe/cfe/arch/mips/common/src/exchandler.c b/cfe/cfe/arch/mips/common/src/exchandler.c
new file mode 100644
index 0000000..d69b980
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/exchandler.c
@@ -0,0 +1,580 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Exception Handler File: exchandler.c
+ *
+ * This is the "C" part of the exception handler and the
+ * associated setup routines. We call these routines from
+ * the assembly-language exception handler.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "sbmips.h"
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "exception.h"
+#include "cfe.h"
+#include "cfe_error.h"
+#include "cfe_iocb.h"
+#include "exchandler.h"
+#include "cpu_config.h"
+#include "bsp_config.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+/*
+ * Temporary until all our CPU packages support a cache error handler
+ */
+
+#ifndef CPUCFG_CERRHANDLER
+#define CPUCFG_CERRHANDLER 0xBFC00000
+#else
+extern void CPUCFG_CERRHANDLER(void);
+#endif
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+exc_handler_t exc_handler;
+extern void _exc_entry(void);
+extern void _exc_setup_locore(long);
+extern void CPUCFG_TLBHANDLER(void);
+extern void cfe_flushcache(uint32_t,long,long);
+extern uint32_t _getstatus(void);
+extern void _setstatus(uint32_t);
+
+static const char *regnames = "0 ATv0v1a0a1a2a3t0t1t2t3t4t5t6t7"
+ "s0s1s2s3s4s5s6s7t8t9k0k1gpspfpra";
+static const char *excnames =
+ "Interrupt" /* 0 */
+ "TLBMod " /* 1 */
+ "TLBMissRd" /* 2 */
+ "TLBMissWr" /* 3 */
+ "AddrErrRd" /* 4 */
+ "AddrErrWr" /* 5 */
+ "BusErrRd " /* 6 */
+ "BusErrWr " /* 7 */
+ "Syscall " /* 8 */
+ "Breakpt " /* 9 */
+ "InvOpcode" /* 10 */
+ "CoProcUnu" /* 11 */
+ "ArithOvfl" /* 12 */
+ "TrapExc " /* 13 */
+ "VCEI " /* 14 */
+ "FPUExc " /* 15 */
+ "CP2Exc " /* 16 */
+ "Exc17 " /* 17 */
+ "Exc18 " /* 18 */
+ "Exc19 " /* 19 */
+ "Exc20 " /* 20 */
+ "Exc21 " /* 21 */
+ "Exc22 " /* 22 */
+ "Watchpt " /* 23 */
+ "Exc24 " /* 24 */
+ "Exc25 " /* 25 */
+ "Exc26 " /* 26 */
+ "Exc27 " /* 27 */
+ "Exc28 " /* 28 */
+ "Exc29 " /* 29 */
+ "Exc30 " /* 30 */
+ "VCED "; /* 31 */
+
+
+
+/* *********************************************************************
+ * cfe_exception(code,info)
+ *
+ * Exception handler. This routine is called when any CPU
+ * exception that is handled by the assembly-language
+ * vectors is reached. The usual thing to do here is just to
+ * reboot.
+ *
+ * Input parameters:
+ * code - exception type
+ * info - exception stack frame
+ *
+ * Return value:
+ * usually reboots
+ ********************************************************************* */
+
+void cfe_exception(int code,uint64_t *info)
+{
+ int idx;
+
+ SETLEDS("EXC!");
+
+ if(exc_handler.catch_exc == 1) {
+ /*Deal with exception without restarting CFE.*/
+
+ /*Clear relevant SR bits*/
+ _exc_clear_sr_exl();
+ _exc_clear_sr_erl();
+
+ /*Reset flag*/
+ exc_handler.catch_exc = 0;
+
+ exc_longjmp_handler();
+ }
+
+
+#ifdef _MIPSREGS32_
+ xprintf("**Exception %d: EPC=%08X, Cause=%08X (%9s)\n",
+ code,(uint32_t)info[XCP0_EPC],
+ (uint32_t)info[XCP0_CAUSE],
+ excnames + G_CAUSE_EXC((uint32_t)info[XCP0_CAUSE])*9);
+ xprintf(" RA=%08X, VAddr=%08X\n",
+ (uint32_t)info[XGR_RA],(uint32_t)info[XCP0_VADDR]);
+ xprintf("\n");
+ for (idx = 0;idx < 32; idx+= 2) {
+ xprintf(" %2s ($%2d) = %08X %2s ($%2d) = %08X\n",
+ regnames+(idx*2),
+ idx,(uint32_t)info[XGR_ZERO+idx],
+ regnames+((idx+1)*2),
+ idx+1,(uint32_t)info[XGR_ZERO+idx+1]);
+ }
+#else
+ xprintf("**Exception %d: EPC=%016llX, Cause=%08X (%9s)\n",
+ code,info[XCP0_EPC],info[XCP0_CAUSE],
+ excnames + G_CAUSE_EXC((uint32_t)info[XCP0_CAUSE])*9);
+ xprintf(" RA=%016llX, VAddr=%016llX\n",
+ info[XGR_RA],info[XCP0_VADDR]);
+ xprintf("\n");
+ for (idx = 0;idx < 32; idx+= 2) {
+ xprintf(" %2s ($%2d) = %016llX %2s ($%2d) = %016llX\n",
+ regnames+(idx*2),
+ idx,info[XGR_ZERO+idx],
+ regnames+((idx+1)*2),
+ idx+1,info[XGR_ZERO+idx+1]);
+ }
+#endif
+
+ xprintf("\n");
+ _exc_restart();
+}
+
+#if (!CFG_BOOTRAM) && (CFG_RUNFROMKSEG0)
+/* *********************************************************************
+ * exc_setup_hw_vector(vecoffset,target,k0code)
+ *
+ * Install a patch of code at the specified offset in low
+ * KSEG0 memory that will jump to 'target' and load k0
+ * with the specified code value. This is used when we
+ * run with RAM vectors.
+ *
+ * Input parameters:
+ * vecoffset - offset into KSEG0
+ * target - location where we should branch when vector is called
+ * k0code - value to load into K0 before branching
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void exc_setup_hw_vector(uint32_t vecoffset,
+ void *target,
+ uint32_t k0code)
+{
+ uint32_t *vec;
+ uint32_t new;
+ uint32_t lower,upper;
+
+ new = (uint32_t) (intptr_t) target; /* warning: assumes compatibility addresses! */
+
+ lower = new & 0xffff;
+ upper = (new >> 16) & 0xffff;
+ if ((lower & 0x8000) != 0) {
+ upper++;
+ }
+
+ /*
+ * Get a KSEG0 version of the vector offset.
+ */
+ vec = (uint32_t *) PHYS_TO_K0(vecoffset);
+
+ /*
+ * Patch in the vector. Note that we have to flush
+ * the L1 Dcache and invalidate the L1 Icache before
+ * we can use this.
+ */
+
+ vec[0] = 0x3c1b0000 | upper; /* lui k1, HIGH(new) */
+ vec[1] = 0x277b0000 | lower; /* addiu k1, k1, LOW(new) */
+ vec[2] = 0x03600008; /* jr k1 */
+ vec[3] = 0x241a0000 | k0code; /* li k0, code */
+
+}
+
+
+/* *********************************************************************
+ * exc_install_ram_vectors()
+ *
+ * Install all of the hardware vectors into low memory,
+ * flush the cache, and clear the BEV bit so we can start
+ * using them.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void exc_install_ram_vectors(void)
+{
+ uint32_t *ptr;
+ int idx;
+
+ /* Debug: blow away the vector area so we can see what we did */
+ ptr = (uint32_t *) PHYS_TO_K0(0);
+ for (idx = 0; idx < 0x1000/sizeof(uint32_t); idx++) *ptr++ = 0;
+
+ /*
+ * Set up the vectors. The cache error handler is set up
+ * specially.
+ */
+
+ exc_setup_hw_vector(MIPS_RAM_VEC_TLBFILL, CPUCFG_TLBHANDLER,XTYPE_TLBFILL);
+ exc_setup_hw_vector(MIPS_RAM_VEC_XTLBFILL, _exc_entry,XTYPE_XTLBFILL);
+ exc_setup_hw_vector(MIPS_RAM_VEC_CACHEERR, _exc_entry,XTYPE_CACHEERR);
+ exc_setup_hw_vector(MIPS_RAM_VEC_EXCEPTION,_exc_entry,XTYPE_EXCEPTION);
+ exc_setup_hw_vector(MIPS_RAM_VEC_INTERRUPT,_exc_entry,XTYPE_INTERRUPT);
+
+ /*
+ * Flush the D-cache and invalidate the I-cache so we can start
+ * using these vectors.
+ */
+
+ cfe_flushcache(CFE_CACHE_FLUSH_D | CFE_CACHE_INVAL_I,0,0);
+
+ /*
+ * Write the handle into our low memory space. If we need to save
+ * other stuff down there, this is a good place to do it.
+ * This call uses uncached writes - we have not touched the
+ * memory in the handlers just yet, so they should not be
+ * in our caches.
+ */
+
+ _exc_setup_locore((intptr_t) CPUCFG_CERRHANDLER);
+
+ /*
+ * Finally, clear BEV so we'll use the vectors in RAM.
+ */
+
+ _setstatus(_getstatus() & ~M_SR_BEV);
+
+ /*
+ * XXX There's a hazard here, but we're not going to worry about
+ * XXX it. It is unlikely we'll use the vectors any time soon.
+ */
+}
+#endif
+
+/* *********************************************************************
+ * cfe_setup_exceptions()
+ *
+ * Set up the exception handlers.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+void cfe_setup_exceptions(void)
+{
+ _exc_setvector(XTYPE_TLBFILL, (void *) cfe_exception);
+ _exc_setvector(XTYPE_XTLBFILL, (void *) cfe_exception);
+ _exc_setvector(XTYPE_CACHEERR, (void *) _exc_cache_crash_sim);
+ _exc_setvector(XTYPE_EXCEPTION,(void *) cfe_exception);
+ _exc_setvector(XTYPE_INTERRUPT,(void *) cfe_exception);
+ _exc_setvector(XTYPE_EJTAG, (void *) cfe_exception);
+
+ exc_handler.catch_exc = 0;
+ q_init( &(exc_handler.jmpbuf_stack));
+
+#if (!CFG_BOOTRAM) && (CFG_RUNFROMKSEG0)
+ /*
+ * Install RAM vectors, and clear the BEV bit in the status
+ * register. Don't do this if we're running from PromICE RAM
+ */
+ exc_install_ram_vectors();
+#endif
+}
+
+
+
+/* *********************************************************************
+ * exc_initialize_block()
+ *
+ * Set up the exception handler. Allow exceptions to be caught.
+ * Allocate memory for jmpbuf and store it away.
+ *
+ * Returns NULL if error in memory allocation.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * jmpbuf_t structure, or NULL if no memory
+ ********************************************************************* */
+jmpbuf_t *exc_initialize_block(void)
+{
+ jmpbuf_t *jmpbuf_local;
+
+ exc_handler.catch_exc = 1;
+
+ /* Create the jmpbuf_t object */
+ jmpbuf_local = (jmpbuf_t *) KMALLOC((sizeof(jmpbuf_t)),0);
+
+ if (jmpbuf_local == NULL) {
+ return NULL;
+ }
+
+ q_enqueue( &(exc_handler.jmpbuf_stack), &((*jmpbuf_local).stack));
+
+ return jmpbuf_local;
+}
+
+/* *********************************************************************
+ * exc_cleanup_block(dq_jmpbuf)
+ *
+ * Remove dq_jmpbuf from the exception handler stack and free
+ * the memory.
+ *
+ * Input parameters:
+ * dq_jmpbuf - block to deallocate
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void exc_cleanup_block(jmpbuf_t *dq_jmpbuf)
+{
+ int count;
+
+ if (dq_jmpbuf == NULL) {
+ return;
+ }
+
+ count = q_count( &(exc_handler.jmpbuf_stack));
+
+ if( count > 0 ) {
+ q_dequeue( &(*dq_jmpbuf).stack );
+ KFREE(dq_jmpbuf);
+ }
+}
+
+/* *********************************************************************
+ * exc_cleanup_handler(dq_jmpbuf,chain_exc)
+ *
+ * Clean a block, then chain to the next exception if required.
+ *
+ * Input parameters:
+ * dq_jmpbuf - current exception
+ * chain_exc - true if we should chain to the next handler
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void exc_cleanup_handler(jmpbuf_t *dq_jmpbuf, int chain_exc)
+{
+ exc_cleanup_block(dq_jmpbuf);
+
+ if( chain_exc == EXC_CHAIN_EXC ) {
+ /*Go to next exception on stack */
+ exc_longjmp_handler();
+ }
+}
+
+
+
+/* *********************************************************************
+ * exc_longjmp_handler()
+ *
+ * This routine long jumps to the exception handler on the top
+ * of the exception stack.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+void exc_longjmp_handler(void)
+{
+ int count;
+ jmpbuf_t *jmpbuf_local;
+
+ count = q_count( &(exc_handler.jmpbuf_stack));
+
+ if( count > 0 ) {
+ jmpbuf_local = (jmpbuf_t *) q_getlast(&(exc_handler.jmpbuf_stack));
+
+ SETLEDS("CFE ");
+
+ lib_longjmp( (*jmpbuf_local).jmpbuf, -1);
+ }
+}
+
+
+/* *********************************************************************
+ * mem_peek(d,addr,type)
+ *
+ * Read memory of the specified type at the specified address.
+ * Exceptions are caught in the case of a bad memory reference.
+ *
+ * Input parameters:
+ * d - pointer to where data should be placed
+ * addr - address to read
+ * type - type of read to do (MEM_BYTE, etc.)
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int mem_peek(void *d, long addr, int type)
+{
+
+ jmpbuf_t *jb;
+
+ jb = exc_initialize_block();
+ if( jb == NULL ) {
+ return CFE_ERR_NOMEM;
+ }
+
+ if (exc_try(jb) == 0) {
+
+ switch (type) {
+ case MEM_BYTE:
+ *(uint8_t *)d = *((volatile uint8_t *) addr);
+ break;
+ case MEM_HALFWORD:
+ *(uint16_t *)d = *((volatile uint16_t *) addr);
+ break;
+ case MEM_WORD:
+ *(uint32_t *)d = *((volatile uint32_t *) addr);
+ break;
+ case MEM_QUADWORD:
+ *(uint64_t *)d = *((volatile uint64_t *) addr);
+ break;
+ default:
+ return CFE_ERR_INV_PARAM;
+ }
+
+ exc_cleanup_block(jb);
+ }
+ else {
+ /*Exception handler*/
+
+ exc_cleanup_handler(jb, EXC_NORMAL_RETURN);
+ return CFE_ERR_GETMEM;
+ }
+
+ return 0;
+}
+
+/* *********************************************************************
+ * Write memory of type at address addr with value val.
+ * Exceptions are caught, handled (error message) and function
+ * returns with 0.
+ *
+ * 1 success
+ * 0 failure
+ ********************************************************************* */
+
+int mem_poke(long addr, uint64_t val, int type)
+{
+
+ jmpbuf_t *jb;
+
+ jb = exc_initialize_block();
+ if( jb == NULL ) {
+ return CFE_ERR_NOMEM;
+ }
+
+ if (exc_try(jb) == 0) {
+
+ switch (type) {
+ case MEM_BYTE:
+ *((volatile uint8_t *) addr) = (uint8_t) val;
+ break;
+ case MEM_HALFWORD:
+ *((volatile uint16_t *) addr) = (uint16_t) val;
+ break;
+ case MEM_WORD:
+ *((volatile uint32_t *) addr) = (uint32_t) val;
+ break;
+ case MEM_QUADWORD:
+ *((volatile uint64_t *) addr) = (uint64_t) val;
+ break;
+ default:
+ return CFE_ERR_INV_PARAM;
+ }
+
+ exc_cleanup_block(jb);
+ }
+ else {
+ /*Exception handler*/
+
+ exc_cleanup_handler(jb, EXC_NORMAL_RETURN);
+ return CFE_ERR_SETMEM;
+ }
+
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/cfe/cfe/arch/mips/common/src/init_mips.S b/cfe/cfe/arch/mips/common/src/init_mips.S
new file mode 100755
index 0000000..3f59539
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/init_mips.S
@@ -0,0 +1,683 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * CPU init module File: init_mips.S
+ *
+ * This module contains the vectors and lowest-level CPU startup
+ * functions for CFE.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "sbmips.h"
+#include "exception.h"
+
+#include "bsp_config.h"
+#include "cpu_config.h"
+
+#ifdef _CFE_
+#include "cfe_devfuncs.h"
+#else
+
+#define cfe_command_restart 0
+#endif
+
+/* BCM63XX specific change. */
+#include "bcm_hwdefs.h"
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#include "mipsmacros.h"
+
+
+/* *********************************************************************
+ * SETLEDS(a,b,c,d)
+ * SETLEDS1(a,b,c,d)
+ *
+ * Sets the on-board LED display (if present). Two variants
+ * of this routine are provided. If you're running KSEG1,
+ * call the SETLEDS1 variant, else call SETLEDS.
+ *
+ * Input parameters:
+ * a,b,c,d - four ASCII characters (literal constants)
+ *
+ * Return value:
+ * a0,k1,ra trashed
+ ********************************************************************* */
+
+#define SETLEDS(a,b,c,d) \
+ li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \
+ CALLINIT_KSEG0(init_table,R_INIT_SETLEDS)
+
+#define SETLEDS1(a,b,c,d) \
+ li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \
+ CALLINIT_KSEG1(init_table,R_INIT_SETLEDS)
+
+
+/* *********************************************************************
+ * Other constants
+ ********************************************************************* */
+
+/*
+ * This is the size of the stack, rounded to KByte boundaries.
+ */
+
+#ifndef CFG_STACK_SIZE
+#error "CFG_STACK_SIZE not defined"
+#else
+#define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023)
+#endif
+
+#ifdef __MIPSEB
+#define TEXTSECTION 0x2e746578 # ".tex", big-endian
+#else
+#define TEXTSECTION 0x7865742e # ".tex", little-endian
+#endif
+
+/*
+ * Duplicates from cfe_iocb.h -- warning!
+ */
+
+#define CFE_CACHE_FLUSH_D 1
+#define CFE_CACHE_INVAL_I 2
+#define CFE_CACHE_INVAL_D 4
+#define CFE_CACHE_INVAL_L2 8
+#define CFE_CACHE_FLUSH_L2 16
+#define CFE_CACHE_INVAL_RANGE 32
+#define CFE_CACHE_FLUSH_RANGE 64
+
+
+/*
+ * To make life easier reading this code, define "KSEGBASE"
+ * to either K0BASE or K1BASE depending on whether we're running
+ * uncached.
+ */
+
+#if CFG_RUNFROMKSEG0
+#define KSEGBASE K0BASE
+#else
+#define KSEGBASE K1BASE
+#endif
+
+
+/* *********************************************************************
+ * Names of registers used in this module
+ ********************************************************************* */
+
+#define RELOCOFFSET s8 /* $30 (fp) */
+#define TEXTOFFSET t9 /* $25 (t9) */
+#define MEMTOP t8 /* $24 (t8) */
+#define TEXTBASE s7 /* $23 (s7) */
+#undef BOOT_OFFSET
+#define BOOT_OFFSET s6 /* $22 (s6) */
+
+ .sdata
+
+#include "initdata.h" /* declare variables we use here */
+
+#if CFG_MULTI_CPUS
+ .globl cfe_spinlock
+cfe_spinlock: .word 0
+#endif
+
+ .extern _fdata
+ .extern _edata
+ .extern _etext
+
+/* *********************************************************************
+ * uninitialized data
+ ********************************************************************* */
+
+ .bss
+
+ .comm __junk,4
+
+/* *********************************************************************
+ * Exception Vectors
+ ********************************************************************* */
+
+ .text
+
+ .set noreorder
+
+/*
+ * Declare the actual vectors. This expands to code that
+ * must be at the very beginning of the text segment.
+ */
+
+DECLARE_VECTOR(0x0000,vec_reset,cpu_reset)
+
+ .set reorder
+
+/* *********************************************************************
+ * Some offsets depend on our current configuration
+ ********************************************************************* */
+
+#define RUNTIME_RELOC_START 0
+#define RUNTIME_RELOC_STOP 0
+
+/* *********************************************************************
+ * Segment Table.
+ *
+ * Addresses of data segments and of certain routines we're going
+ * to call from KSEG1. These are here mostly for the embedded
+ * PIC case, since we can't count on the 'la' instruction to
+ * do the expected thing (the assembler expands it into a macro
+ * for doing GP-relative stuff, and the code is NOT GP-relative.
+ * So, we (relocatably) get the offset of this table and then
+ * index within it.
+ *
+ * Pointer values in this segment will be relative to KSEG0 for
+ * cached versions of CFE, so we need to OR in K1BASE in the
+ * case of calling to a uncached address.
+ *
+ * The LOADREL macro handles most of the nastiness here.
+ ********************************************************************* */
+
+#include "segtable.h"
+#include "cfe.h"
+
+ .org 0x570
+ .byte 'c','f','e','-','v',CFE_VER_MAJOR,CFE_VER_MINOR,CFE_VER_BUILD,BCM63XX_MAJOR,BCM63XX_MINOR # CFE version info for applications
+ .org 0x580 # move past exception vectors
+
+ /*
+ * BCM963XX NVRAM Data Storage
+ */
+
+ .globl nvram_data_storage
+nvram_data_storage:
+ .word NVRAM_DATA_ID
+ .space 0x400
+
+ .globl segment_table
+segment_table:
+ _LONG_ _etext # [ 0] End of text (R_SEG_ETEXT)
+ _LONG_ _fdata # [ 1] Beginning of data (R_SEG_FDATA)
+ _LONG_ _edata # [ 2] End of data (R_SEG_EDATA)
+ _LONG_ _end # [ 3] End of BSS (R_SEG_END)
+ _LONG_ _ftext # [ 4] Beginning of text (R_SEG_FTEXT)
+ _LONG_ _fbss # [ 5] Beginning of BSS (R_SEG_FBSS)
+ _LONG_ _gp # [ 6] Global Pointer (R_SEG_GP)
+ _LONG_ 0 # [ 7] Beginning of reloc entries
+ _LONG_ 0 # [ 8] End of reloc entries
+ _LONG_ 0 # [ 9] R_SEG_APIENTRY
+
+/* *********************************************************************
+ * Init Table.
+ *
+ * This is like segment_table except it contains pointers to
+ * routines used during initialization. It serves both as a
+ * table for doing PIC stuff and also to separate out
+ * machine-specific init routines.
+ *
+ * The CALLINIT_xxx macros are used to call routines in this table.
+ ********************************************************************* */
+
+
+ .globl init_table
+init_table:
+ _LONG_ board_earlyinit # [ 0] R_INIT_EARLYINIT
+ _LONG_ board_setleds # [ 1] R_INIT_SETLEDS
+ _LONG_ board_draminfo # [ 2] R_INIT_DRAMINFO
+ _LONG_ CPUCFG_CPUINIT # [ 3] R_INIT_CPUINIT
+ _LONG_ CPUCFG_ALTCPU_START1 # [ 4] R_INIT_ALTCPU_START1
+ _LONG_ CPUCFG_ALTCPU_START2 # [ 5] R_INIT_ALTCPU_START2
+ _LONG_ CPUCFG_ALTCPU_RESET # [ 6] R_INIT_ALTCPU_RESET
+ _LONG_ CPUCFG_CPURESTART # [ 7] R_INIT_CPURESTART
+ _LONG_ CPUCFG_DRAMINIT # [ 8] R_INIT_DRAMINIT
+ _LONG_ CPUCFG_CACHEOPS # [ 9] R_INIT_CACHEOPS
+ _LONG_ CPUCFG_TLBHANDLER # [ 10] R_INIT_TLBHANDLER
+ _LONG_ cfe_main # [ 11] R_INIT_CMDSTART
+ _LONG_ cfe_command_restart # [ 12] R_INIT_CMDRESTART
+ _LONG_ cfe_doxreq # [ 13] R_INIT_DOXREQ
+ _LONG_ CPUCFG_TP1_SWITCH # [ 14] R_INIT_TP1_SWITCH
+ _LONG_ cfe_size_ram # [ 15] R_INIT_SIZERAM
+
+/* *********************************************************************
+ * CPU Startup Code
+ ********************************************************************* */
+
+cpu_reset:
+
+ /*
+ * Start with GP as zero. Nobody should touch
+ * this or set it to any other value until we're ready
+ * to use it. This is used to tell when we should start
+ * using relocated references in the init table,
+ * so beware! (see CALLINIT_RELOC in mipsmacros.h)
+ */
+
+ move gp,zero # start with no GP.
+
+ .set noreorder
+ bal 1f
+ nop
+1: nop
+ .set reorder
+ li BOOT_OFFSET, 0x1fff0000
+ and BOOT_OFFSET, ra
+
+#------------------------------------------------------------------------------
+
+ /*
+ * Do low-level board initialization. This is our first
+ * chance to customize the startup sequence.
+ */
+ move a0, BOOT_OFFSET
+
+ CALLINIT_KSEG1(init_table,R_INIT_EARLYINIT)
+
+ SETLEDS1('H','E','L','O')
+
+ CALLINIT_KSEG1(init_table,R_INIT_CPUINIT)
+
+#------------------------------------------------------------------------------
+
+ /*
+ * Now, switch from KSEG1 to KSEG0
+ */
+
+#if CFG_RUNFROMKSEG0
+ bal cpu_kseg0_switch
+#endif
+
+#------------------------------------------------------------------------------
+ /*
+ * Now running on cpu0 in K0SEG.
+ */
+
+#if CFG_CMT
+ /*
+ * Check if the thread switch is required. If we are already
+ * running on thread 1 this function will do nothing and just return
+ * If we are running on thread 0 this function will take thread 1
+ * out of reset and put thread 0 to sleep waiting for singnal from
+ * thread 1.
+ */
+ CALLINIT_KSEG0(init_table,R_INIT_TP1_SWITCH)
+#endif
+
+#if CFG_INIT_DRAM
+ SETLEDS('D','R','A','M')
+
+ CALLINIT_KSEG0(init_table,R_INIT_DRAMINFO)
+
+ move a0,v0 # pass these params
+ CALLINIT_KSEG0(init_table,R_INIT_DRAMINIT)
+ CALLINIT_KSEG0(init_table,R_INIT_SIZERAM)
+ move k0,v0 # Save in k0 for now
+#else
+ li k0,(CFG_DRAM_SIZE * 1024)
+#endif
+
+#------------------------------------------------------------------------------
+
+#if CFG_BOOTRAM
+ b have_ram # No RAM is ok if using emulator RAM
+#endif
+
+ bne k0,zero,have_ram
+
+ SETLEDS('R','A','M','X') # die here if no ram
+
+die1: b die1
+
+have_ram:
+
+ /*
+ * If this is the 64-bit version, turn on the KX bit
+ * to allow 64-bit accesses.
+ */
+
+#ifdef __long64
+ mfc0 t0,C0_SR
+ or t0,t0,M_SR_KX
+ mtc0 t0,C0_SR
+#endif
+
+#------------------------------------------------------------------------------
+ /*
+ * K0 contains the RAM size (and therefore the top of RAM
+ * offset). Start there, and subtract the amount of memory
+ * we expect to use. If we have more than 256MB of
+ * physical memory, work backwards from the 256MB
+ * boundary.
+ */
+
+__CalcMemTop: li MEMTOP,256 # 256MB boundary
+ bgt k0,MEMTOP,1f # use 256MB if k0 is greater
+ move MEMTOP,k0 # otherwise keep top
+1: sll MEMTOP,20 # make into byte amount
+
+ li RELOCOFFSET,0 # not relocating, no offset
+ li TEXTOFFSET,0
+
+ /*
+ * DRAM is now running, and we're alive in cacheable memory
+ * on cpu0 in K0SEG. Set up GP.
+ */
+
+ LOADREL(a0,segment_table)
+ LR gp,R_SEG_GP(a0)
+ add gp,RELOCOFFSET
+
+#------------------------------------------------------------------------------
+ /*
+ * Zero BSS
+ */
+
+ SETLEDS('Z','B','S','S')
+
+ LOADREL(a0,segment_table)
+__ZeroBss:
+
+ LR v0,R_SEG_FBSS(a0)
+ LR v1,R_SEG_END(a0)
+ ADD v0,RELOCOFFSET # Relocate to actual data segment
+ ADD v1,RELOCOFFSET
+
+1: SR zero,0(v0) # Zero one cacheline at a time
+ SR zero,(REGSIZE*1)(v0)
+ SR zero,(REGSIZE*2)(v0)
+ SR zero,(REGSIZE*3)(v0)
+ add v0,REGSIZE*4
+ blt v0,v1,1b
+
+#------------------------------------------------------------------------------
+ /*
+ * Copy code
+ */
+
+ SETLEDS('C','O','D','E')
+
+ LOADREL(a0,segment_table)
+__CopyCode:
+
+ LR t1,R_SEG_FTEXT(a0) # destination address
+ move TEXTBASE,t1
+
+ LR t2,R_SEG_FTEXT(a0) # Source address
+ FIXUP (t2);
+ LR t3,R_SEG_ETEXT(a0)
+ FIXUP (t3);
+
+1: LR t4,0(t2) # read one cache line
+ LR t5,(REGSIZE*1)(t2)
+ LR t6,(REGSIZE*2)(t2)
+ LR t7,(REGSIZE*3)(t2)
+ SR t4,0(t1) # write one cache line
+ SR t5,(REGSIZE*1)(t1)
+ SR t6,(REGSIZE*2)(t1)
+ SR t7,(REGSIZE*3)(t1)
+ add t1,REGSIZE*4
+ add t2,REGSIZE*4
+ bltu t2,t3,1b
+
+#------------------------------------------------------------------------------
+ /*
+ * Copy initialized data
+ */
+
+#if (CFG_BOOTRAM == 0)
+
+ SETLEDS('D','A','T','A')
+
+ LOADREL(a0,segment_table)
+
+__CopyData:
+ LR t1,R_SEG_FDATA(a0)
+ FIXUP (t1);
+ li t0,15
+ add t1,t0
+ not t0
+ and t1,t0 # t1 = _etext rounded up to 16-byte boundary
+
+ LR t2,R_SEG_FDATA(a0)
+ LR t3,R_SEG_EDATA(a0)
+ ADD t2,RELOCOFFSET # Relocate to actual data segment
+ ADD t3,RELOCOFFSET
+
+1: LR t4,0(t1) # read one cache line
+ LR t5,(REGSIZE*1)(t1)
+ LR t6,(REGSIZE*2)(t1)
+ LR t7,(REGSIZE*3)(t1)
+ SR t4,0(t2) # write one cache line
+ SR t5,(REGSIZE*1)(t2)
+ SR t6,(REGSIZE*2)(t2)
+ SR t7,(REGSIZE*3)(t2)
+ add t1,(REGSIZE*4)
+ add t2,(REGSIZE*4)
+ bltu t2,t3,1b
+
+#endif
+
+#------------------------------------------------------------------------------
+
+ /*
+ * Flush the cache, then switch to relocated code
+ * We need to flush the cache since we just moved the code and
+ * it may still live in our L1 DCache. We also need to
+ * flush L2, since there are some rare times we run
+ * uncached from DRAM, like when we start/stop a CPU.
+ *
+ * In the case of running completely uncached, don't flush the
+ * cache. It should not have any dirty lines in it, but you
+ * never know...
+ */
+
+__GoRelo:
+
+#if CFG_RUNFROMKSEG0
+ SETLEDS('L','1','2','F')
+
+ li a0,CFE_CACHE_FLUSH_D | CFE_CACHE_FLUSH_L2
+ CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS)
+ li a0,CFE_CACHE_INVAL_I
+ CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS)
+#endif /* CFG_RUNFROMKSEG0 */
+
+ la t0,gorelo # Now jump to an address code was compiled for
+ j t0 # and go there
+gorelo: nop
+ li BOOT_OFFSET, 0 # no longer running at offset
+
+ /*
+ * Remember total amount of memory. This is *still* in k0
+ * after all this time. Hopefully.
+ */
+
+__MemVars:
+ SR k0,mem_totalsize
+ SR RELOCOFFSET,mem_datareloc
+
+ move v0,zero
+
+ LOADREL(a0,segment_table) # trashed by l2 cache flush
+ LR v0,R_SEG_FDATA(a0)
+ ADD v0,RELOCOFFSET
+ LR v1,R_SEG_END(a0)
+ ADD v1,RELOCOFFSET
+
+ SR v0,mem_bottomofmem
+ SR v1,mem_heapstart
+
+ add v1,(CFG_HEAP_SIZE*1024) # Otherwise
+ add v1,STACK_SIZE
+ SR v1,mem_topofmem
+
+ SR TEXTOFFSET,mem_textreloc
+
+ /* At this point it's safe to use the CALLINIT_RELOC macro */
+
+ LR t1,R_SEG_FTEXT(a0)
+ FIXUP (t1);
+ LR t0,R_SEG_ETEXT(a0)
+ FIXUP (t0);
+ sub t0,t0,t1
+ SR t0,mem_textsize
+ add t1,TEXTOFFSET
+ SR t1,mem_textbase
+
+
+#------------------------------------------------------------------------------
+
+ /*
+ * Stash away some config register stuff
+ */
+
+ mfc0 v0,C0_PRID
+ SR v0,cpu_prid
+
+
+#------------------------------------------------------------------------------
+
+ /*
+ * Set up the "C" stack and jump to the main routine.
+ */
+
+ SETLEDS('M','A','I','N')
+
+ LR sp,mem_heapstart
+ ADD sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8)
+ li a0,0 # call as "cfe_main(0,0)"
+ li a1,0
+
+ CALLINIT_RELOC(init_table,R_INIT_CMDSTART) # should not return
+
+/* *********************************************************************
+ * CFE_LAUNCH
+ *
+ * Start the user program. The program is passed a handle
+ * that must be passed back when calling the firmware.
+ *
+ * Parameters passed to the called program are as follows:
+ *
+ * a0 - CFE handle
+ * a1 - entry vector
+ * a2 - reserved, will be 0
+ * a3 - entrypoint signature.
+ *
+ * Input parameters:
+ * a0 - entry vector
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+LEAF(cfe_launch)
+
+ sub sp,8
+ SR a0,0(sp)
+
+ /*
+ * This function runs in RAM so BOOT_OFFSET is 0. It is called from
+ * C which could have modified the BOOT_OFFSET register, s6.
+ */
+ li BOOT_OFFSET, 0
+
+
+ /*
+ * Mask all interrupts.
+ */
+ mfc0 v0,C0_SR # Get current interrupt flag
+ li v1,M_SR_IE # master interrupt control
+ not v1 # disable interrupts
+ and v0,v1 # SR now has IE=0
+ mtc0 v0,C0_SR # put back into CP0
+
+
+ /*
+ * Flush the D-Cache, since the program we loaded is "data".
+ * Invalidate the I-Cache, so that addresses in the program
+ * region will miss and need to be filled from the data we
+ * just flushed above.
+ */
+
+ li a0,CFE_CACHE_FLUSH_D|CFE_CACHE_INVAL_I
+ CALLINIT_RELOC(init_table,R_INIT_CACHEOPS)
+
+
+ /*
+ * Set things up for launching the program. Pass the
+ * handle in A0 - apps need to remember that and pass it
+ * back.
+ */
+
+ j RunProgram
+
+END(cfe_launch)
+
+ /*
+ * This is a nice place to set a breakpoint.
+ */
+LEAF(RunProgram)
+ LR t0,0(sp) # entry point
+
+ j t0 # go for it.
+END(RunProgram)
+
+/* *********************************************************************
+ * CPU_KSEG0_SWITCH
+ *
+ * Hack the return address so we will come back in KSEG0
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(cpu_kseg0_switch)
+
+ and ra,(K0SIZE-1)
+ or ra,K0BASE
+ jr ra
+
+END(cpu_kseg0_switch)
+
+/* *********************************************************************
+ * End
+ ********************************************************************* */
+
+
diff --git a/cfe/cfe/arch/mips/common/src/init_ram.S b/cfe/cfe/arch/mips/common/src/init_ram.S
new file mode 100755
index 0000000..2531700
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/init_ram.S
@@ -0,0 +1,889 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * CPU init module File: init_ram.S
+ *
+ * This module contains the vectors and lowest-level CPU startup
+ * functions for CFE.
+ *
+ * This is very similar to "init_mips.S" but is used when
+ * you want to locate CFE in DRAM, loading it like an
+ * application program.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "sbmips.h"
+#include "exception.h"
+
+#include "bsp_config.h"
+#include "cpu_config.h"
+
+#include "cfe_devfuncs.h"
+
+/* *********************************************************************
+ * Check some stuff
+ ********************************************************************* */
+
+#if CFG_RELOC
+#error "RAM version is not compatible with relocation."
+#endif
+#if !(CFG_RUNFROMKSEG0)
+#error "RAM version should be run cached"
+#endif
+
+#if CFG_MULTI_CPUS
+#error "Multiple CPUs not compatible with RAM version"
+#endif
+
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#include "mipsmacros.h"
+
+
+/* *********************************************************************
+ * SETLEDS(a,b,c,d)
+ *
+ * Sets the on-board LED display (if present).
+ *
+ * Input parameters:
+ * a,b,c,d - four ASCII characters (literal constants)
+ *
+ * Return value:
+ * a0,k1,ra trashed
+ ********************************************************************* */
+
+
+#define SETLEDS(a,b,c,d) \
+ li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \
+ jal board_setleds ;
+
+
+/* *********************************************************************
+ * Other constants
+ ********************************************************************* */
+
+/*
+ * This is the size of the stack, rounded to KByte boundaries.
+ */
+
+#ifndef CFG_STACK_SIZE
+#error "CFG_STACK_SIZE not defined"
+#else
+#define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023)
+#endif
+
+/*
+ * Duplicates from cfe_iocb.h -- warning!
+ */
+
+#define CFE_CACHE_FLUSH_D 1
+#define CFE_CACHE_INVAL_I 2
+#define CFE_CACHE_INVAL_D 4
+#define CFE_CACHE_INVAL_L2 8
+#define CFE_CACHE_FLUSH_L2 16
+#define CFE_CACHE_INVAL_RANGE 32
+#define CFE_CACHE_FLUSH_RANGE 64
+
+
+/*
+ * To make life easier reading this code, define "KSEGBASE"
+ * to either K0BASE or K1BASE depending on whether we're running
+ * uncached.
+ */
+
+#define KSEGBASE K0BASE /* RAM version always cached */
+
+
+/* *********************************************************************
+ * Names of registers used in this module
+ ********************************************************************* */
+
+ .sdata
+
+#include "initdata.h" /* declare variables we use here */
+
+#if CFG_MULTI_CPUS
+ .globl cfe_spinlock
+cfe_spinlock: .word 0
+#endif
+
+ .extern _fdata
+ .extern _edata
+ .extern _etext
+
+/* *********************************************************************
+ * uninitialized data
+ ********************************************************************* */
+
+ .bss
+
+ .comm __junk,4
+
+ .text
+
+ .set noreorder
+
+
+/* *********************************************************************
+ * CFE Entry Point (used by OS boot loaders and such)
+ ********************************************************************* */
+
+ .set noreorder
+
+ .globl vec_reset
+
+vec_reset: b cpu_reset
+ nop
+
+
+vec_apientry: b cpu_apientry
+ nop
+ .word CFE_EPTSEAL
+ .word CFE_EPTSEAL
+
+ .set reorder
+
+
+/* *********************************************************************
+ * Segment Table.
+ *
+ * Addresses of data segments and of certain routines we're going
+ * to call from KSEG1. These are here mostly for the embedded
+ * PIC case, since we can't count on the 'la' instruction to
+ * do the expected thing (the assembler expands it into a macro
+ * for doing GP-relative stuff, and the code is NOT GP-relative.
+ * So, we (relocatably) get the offset of this table and then
+ * index within it.
+ *
+ * Pointer values in this segment will be relative to KSEG0 for
+ * cached versions of CFE, so we need to OR in K1BASE in the
+ * case of calling to a uncached address.
+ *
+ * The LOADREL macro handles most of the nastiness here.
+ ********************************************************************* */
+
+
+#include "segtable.h"
+
+ .globl segment_table
+segment_table:
+ _LONG_ _etext # [ 0] End of text (R_SEG_ETEXT)
+ _LONG_ _fdata # [ 1] Beginning of data (R_SEG_FDATA)
+ _LONG_ _edata # [ 2] End of data (R_SEG_EDATA)
+ _LONG_ _end # [ 3] End of BSS (R_SEG_END)
+ _LONG_ _ftext # [ 4] Beginning of text (R_SEG_FTEXT)
+ _LONG_ _fbss # [ 5] Beginning of BSS (R_SEG_FBSS)
+ _LONG_ _gp # [ 6] Global Pointer (R_SEG_GP)
+ _LONG_ 0 # [ 7] Beginning of reloc entries
+ _LONG_ 0 # [ 8] End of reloc entries
+ _LONG_ cpu_apientry # [ 9] R_SEG_APIENTRY
+
+
+/* *********************************************************************
+ * Init Table.
+ *
+ * This is like segment_table except it contains pointers to
+ * routines used during initialization. It serves both as a
+ * table for doing PIC stuff and also to separate out
+ * machine-specific init routines.
+ *
+ * The CALLINIT_xxx macros are used to call routines in this table.
+ ********************************************************************* */
+
+
+ .globl init_table
+init_table:
+ _LONG_ board_earlyinit # [ 0] R_INIT_EARLYINIT
+ _LONG_ board_setleds # [ 1] R_INIT_SETLEDS
+ _LONG_ board_draminfo # [ 2] R_INIT_DRAMINFO
+ _LONG_ CPUCFG_CPUINIT # [ 3] R_INIT_CPUINIT
+ _LONG_ CPUCFG_ALTCPU_START1 # [ 4] R_INIT_ALTCPU_START1
+ _LONG_ CPUCFG_ALTCPU_START2 # [ 5] R_INIT_ALTCPU_START2
+ _LONG_ CPUCFG_ALTCPU_RESET # [ 6] R_INIT_ALTCPU_RESET
+ _LONG_ CPUCFG_CPURESTART # [ 7] R_INIT_CPURESTART
+ _LONG_ CPUCFG_DRAMINIT # [ 8] R_INIT_DRAMINIT
+ _LONG_ CPUCFG_CACHEOPS # [ 9] R_INIT_CACHEOPS
+ _LONG_ CPUCFG_TLBHANDLER # [ 10] R_INIT_TLBHANDLER
+ _LONG_ cfe_main # [ 11] R_INIT_CMDSTART
+ _LONG_ cfe_command_restart # [ 12] R_INIT_CMDRESTART
+ _LONG_ cfe_doxreq # [ 13] R_INIT_DOXREQ
+ _LONG_ CPUCFG_TP1_SWITCH # [ 14] R_INIT_TP1_SWITCH
+ _LONG_ bcmcore_null # [ 15] R_INIT_SIZERAM
+
+/* *********************************************************************
+ * CPU Startup Code
+ ********************************************************************* */
+
+
+cpu_reset:
+
+#------------------------------------------------------------------------------
+
+ /*
+ * Do low-level board initialization. This is our first
+ * chance to customize the startup sequence.
+ */
+
+ CALLINIT_KSEG0(init_table,R_INIT_EARLYINIT)
+
+ SETLEDS('H','E','L','O')
+
+#------------------------------------------------------------------------------
+
+ /*
+ * DRAM is now running, and we're alive in cacheable memory
+ * on cpu0 in K0SEG. Set up GP.
+ */
+
+ LOADREL(a0,segment_table)
+ LR gp,R_SEG_GP(a0)
+
+#------------------------------------------------------------------------------
+ /*
+ * Zero BSS
+ */
+
+ SETLEDS('Z','B','S','S')
+
+ LOADREL(a0,segment_table)
+__ZeroBss:
+
+ LR v0,R_SEG_FBSS(a0)
+ LR v1,R_SEG_END(a0)
+
+1: SR zero,0(v0) # Zero one cacheline at a time
+ SR zero,(REGSIZE*1)(v0)
+ SR zero,(REGSIZE*2)(v0)
+ SR zero,(REGSIZE*3)(v0)
+ add v0,REGSIZE*4
+ blt v0,v1,1b
+
+
+#------------------------------------------------------------------------------
+
+ li k0,256 # memory size in megabytes
+
+
+#ifdef __long64
+ mfc0 t0,C0_SR
+ or t0,t0,M_SR_KX
+ mtc0 t0,C0_SR
+#endif
+
+#------------------------------------------------------------------------------
+
+ /*
+ * Remember total amount of memory. This is *still* in k0
+ * after all this time. Hopefully.
+ */
+
+__MemVars:
+ SR k0,mem_totalsize
+ SR zero,mem_datareloc
+
+ move v0,zero
+
+ LOADREL(a0,segment_table) # trashed by l2 cache flush
+ LR v0,R_SEG_FTEXT(a0) # bottom = beginning of text
+ LR v1,R_SEG_END(a0)
+
+ SR v0,mem_bottomofmem
+ SR v1,mem_heapstart
+
+ add v1,(CFG_HEAP_SIZE*1024) # Otherwise
+ add v1,STACK_SIZE
+ SR v1,mem_topofmem
+
+ SR zero,mem_textreloc
+
+
+ LR t1,R_SEG_FTEXT(a0)
+ LR t0,R_SEG_ETEXT(a0)
+ sub t0,t0,t1
+ SR t0,mem_textsize
+ SR t1,mem_textbase
+
+
+#------------------------------------------------------------------------------
+
+#if CFG_MULTI_CPUS
+ /*
+ * Let secondary CPU(s) run their idle loops. Set the
+ * mailbox register to our relocation factor so we can read
+ * it out of the mailbox register and relocate GP properly.
+ */
+
+ move a0,zero
+ CALLINIT_KSEG0(init_table,R_INIT_ALTCPU_START2)
+#endif
+
+ /*
+ * Stash away some config register stuff
+ */
+
+ mfc0 v0,C0_PRID
+ SR v0,cpu_prid
+
+
+#------------------------------------------------------------------------------
+
+ /*
+ * Set up the "C" stack and jump to the main routine.
+ */
+
+ SETLEDS('M','A','I','N')
+
+ LR sp,mem_heapstart
+ ADD sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8)
+ li a0,0 # call as "cfe_main(0,0)"
+ li a1,0
+
+ CALLINIT_KSEG0(init_table,R_INIT_CMDSTART) # should not return
+
+
+ /*
+ * Terminate the simulator.
+ */
+
+crash_sim: li $2,1
+ li $4,0
+ syscall 0xCA
+ b cpu_reset
+
+
+
+/* *********************************************************************
+ * CFE_WARMSTART
+ *
+ * Restart the command interpreter
+ *
+ * Input parameters:
+ * A0 - command status
+ * nothing (GP has already been set up for us)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(cfe_warmstart)
+
+ SR a0,0(sp) # store on old stack
+ LOADREL(v0,init_table)
+ LR v0,R_INIT_CPURESTART(v0)
+ jal v0 # had better not trash GP or K1
+ LR a0,0(sp)
+
+ LR sp,mem_heapstart
+ ADD sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8)
+
+ /*
+ * If someone called the API to do a warm start, clear the
+ * spin lock, since the call will never return.
+ */
+
+#if CFG_MULTI_CPUS
+ SPIN_UNLOCK(cfe_spinlock,t0)
+#endif
+
+ CALLINIT_KSEG0(init_table,R_INIT_CMDRESTART) # should not return
+
+END(cfe_warmstart)
+
+/* *********************************************************************
+ * CFE_FLUSHCACHE
+ *
+ * Perform certain cache operations
+ *
+ * Input parameters:
+ * a0 - flags (CFE_CACHE_xxx flags, or zero for a default)
+ * a1,a2 - start/end of range for "range invalidate" operations
+ * (not used otherwise)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(_cfe_flushcache)
+
+ sub sp,32
+ SR ra,0(sp)
+ SR a0,8(sp)
+ SR s0,16(sp)
+ SR v1,24(sp)
+
+
+ CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS)
+
+ LR v1,24(sp)
+ LR s0,16(sp)
+ LR a0,8(sp)
+ LR ra,0(sp)
+ add sp,32
+ j ra
+
+END(_cfe_flushcache)
+
+
+/* *********************************************************************
+ * CFE_LAUNCH
+ *
+ * Start the user program. The program is passed a handle
+ * that must be passed back when calling the firmware.
+ *
+ * Parameters passed to the called program are as follows:
+ *
+ * a0 - CFE handle
+ * a1 - entry vector
+ * a2 - reserved, will be 0
+ * a3 - entrypoint signature.
+ *
+ * Input parameters:
+ * a0 - entry vector
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+LEAF(cfe_launch)
+
+ sub sp,8
+ SR a0,0(sp)
+
+ /*
+ * Mask all interrupts.
+ */
+ mfc0 v0,C0_SR # Get current interrupt flag
+ li v1,M_SR_IE # master interrupt control
+ not v1 # disable interrupts
+ and v0,v1 # SR now has IE=0
+ mtc0 v0,C0_SR # put back into CP0
+
+ /*
+ * Flush the D-Cache, since the program we loaded is "data".
+ * Invalidate the I-Cache, so that addresses in the program
+ * region will miss and need to be filled from the data we
+ * just flushed above.
+ */
+
+ li a0,CFE_CACHE_FLUSH_D|CFE_CACHE_INVAL_I
+ CALLINIT_KSEG0(init_table,R_INIT_CACHEOPS)
+
+ /*
+ * Set things up for launching the program. Pass the
+ * handle in A0 - apps need to remember that and pass it
+ * back.
+ */
+
+ j RunProgram
+
+END(cfe_launch)
+
+ /*
+ * This is a nice place to set a breakpoint.
+ */
+LEAF(RunProgram)
+
+ LOADREL(a2,segment_table)
+ LR a2,R_SEG_APIENTRY(a2) # A2 = code entry
+ move t0,a0 #
+ move a1,zero # A1 = 0
+ move a0,gp # A0 = handle
+ li a3,CFE_EPTSEAL # A3 = entrypoint signature
+ LR t0,0(sp) # entry point
+ j t0 # go for it.
+END(RunProgram)
+
+
+
+
+/* *********************************************************************
+ * CFE_LEDS
+ *
+ * Set the on-board LEDs.
+ *
+ * Input parameters:
+ * a0 - LEDs
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(cfe_leds)
+
+ j board_setleds # jump to BSP routine
+
+END(cfe_leds)
+
+/* *********************************************************************
+ * TLB Fill Exeption Handler
+ ********************************************************************* */
+
+cpu_tlbfill:
+ move k0,ra # Save, we're about to trash
+ LOADREL(k1,init_table) # Load offset of init table
+ LR k1,R_INIT_TLBHANDLER(k1) # Get entry from table
+ move ra,k0 # restore trashed ra
+ j k1 # Dispatch to handler
+
+/* *********************************************************************
+ * XTLB Fill Exception Handler
+ ********************************************************************* */
+
+cpu_xtlbfill:
+ j _exc_entry
+
+/* *********************************************************************
+ * Cache Error Exception Handler
+ ********************************************************************* */
+
+cpu_cacheerr:
+ j _exc_entry
+
+
+/* *********************************************************************
+ * General Exception Handler
+ ********************************************************************* */
+
+cpu_exception:
+ j _exc_entry
+
+
+/* *********************************************************************
+ * General Interrupt Handler
+ ********************************************************************* */
+
+cpu_interrupt:
+ j _exc_entry
+
+
+/* *********************************************************************
+ * EJTAG Debug Exception Handler
+ ********************************************************************* */
+
+cpu_ejtag:
+ j cpu_reset
+
+/* *********************************************************************
+ * cpu_apientry(handle,iocb)
+ *
+ * API entry point for external apps.
+ *
+ * Input parameters:
+ * a0 - firmware handle (used to determine the location of
+ * our relocated data)
+ * a1 - pointer to IOCB to execute
+ *
+ * Return value:
+ * v0 - return code, 0 if ok
+ ********************************************************************* */
+
+#define _regidx(x) ((x)*8)
+
+#define CAE_SRSAVE _regidx(0)
+#define CAE_GPSAVE _regidx(1)
+#define CAE_RASAVE _regidx(2)
+#define CAE_S0SAVE _regidx(3)
+#define CAE_S1SAVE _regidx(4)
+#define CAE_S2SAVE _regidx(5)
+#define CAE_S3SAVE _regidx(6)
+#define CAE_S4SAVE _regidx(7)
+#define CAE_S5SAVE _regidx(8)
+#define CAE_S6SAVE _regidx(9)
+#define CAE_S7SAVE _regidx(10)
+
+#define CAE_STKSIZE _regidx(11)
+
+LEAF(cpu_apientry)
+
+ sub sp,CAE_STKSIZE # Make room for our stuff
+
+ mfc0 v0,C0_SR # Get current interrupt flag
+ SR v0,CAE_SRSAVE(sp) # save on stack
+ li t0,M_SR_IE # master interrupt control
+ not t0 # disable interrupts
+ and v0,t0 # SR now has IE=0
+ mtc0 v0,C0_SR # put back into CP0
+
+ SR gp,CAE_GPSAVE(sp) # save GP
+ SR ra,CAE_RASAVE(sp) # and old RA
+
+ SR s0,CAE_S0SAVE(sp)
+ SR s1,CAE_S1SAVE(sp)
+ SR s2,CAE_S2SAVE(sp)
+ SR s3,CAE_S3SAVE(sp)
+ SR s4,CAE_S4SAVE(sp)
+ SR s5,CAE_S5SAVE(sp)
+ SR s6,CAE_S6SAVE(sp)
+ SR s7,CAE_S7SAVE(sp)
+
+ move gp,a0 # set up new GP
+ move a0,a1 # A0 points at IOCB
+
+
+#if CFG_MULTI_CPUS
+ SPIN_LOCK(cfe_spinlock,t0,t1)
+#endif
+
+ CALLINIT_KSEG0(init_table,R_INIT_DOXREQ) # should not return
+
+#if CFG_MULTI_CPUS
+ SPIN_UNLOCK(cfe_spinlock,t0)
+#endif
+
+ #
+ # Restore the saved registers.
+ #
+
+ LR s7,CAE_S7SAVE(sp)
+ LR s6,CAE_S6SAVE(sp)
+ LR s5,CAE_S5SAVE(sp)
+ LR s4,CAE_S4SAVE(sp)
+ LR s3,CAE_S3SAVE(sp)
+ LR s2,CAE_S2SAVE(sp)
+ LR s1,CAE_S1SAVE(sp)
+ LR s0,CAE_S0SAVE(sp)
+
+ LR ra,CAE_RASAVE(sp) # unwind the stack
+ LR gp,CAE_GPSAVE(sp)
+
+ LR t0,CAE_SRSAVE(sp) # old interrupt mask
+
+ add sp,CAE_STKSIZE # restore old stack pointer
+
+ mtc0 t0,C0_SR # restore interrupts
+ j ra
+ nop
+
+END(cpu_apientry)
+
+
+/* *********************************************************************
+ * CPU_KSEG0_SWITCH
+ *
+ * Hack the return address so we will come back in KSEG0
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(cpu_kseg0_switch)
+
+ and ra,(K0SIZE-1)
+ or ra,K0BASE
+ jr ra
+
+END(cpu_kseg0_switch)
+
+
+
+
+/* *********************************************************************
+ * _GETSTATUS()
+ *
+ * Read the STATUS register into v0
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * v0 - Status register
+ ********************************************************************* */
+
+LEAF(_getstatus)
+
+ mfc0 v0,C0_SR
+ j ra
+END(_getstatus)
+
+
+/* *********************************************************************
+ * _SETSTATUS()
+ *
+ * Set the STATUS register to the value in a0
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * v0 - Status register
+ ********************************************************************* */
+
+LEAF(_setstatus)
+
+ mtc0 a0,C0_SR
+ j ra
+END(_setstatus)
+
+/* *********************************************************************
+ * _GETCAUSE()
+ *
+ * Read the CAUSE register into v0
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * v0 - Cause register
+ ********************************************************************* */
+
+LEAF(_getcause)
+
+ mfc0 v0,C0_CAUSE
+ j ra
+END(_getcause)
+
+
+/* *********************************************************************
+ * _GETTICKS()
+ *
+ * Read the COUNT register into v0
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * v0 - count register
+ ********************************************************************* */
+
+LEAF(_getticks)
+
+ mfc0 v0,C0_COUNT
+ j ra
+END(_getticks)
+
+
+/* *********************************************************************
+ * _SETALARM(ticks)
+ *
+ * Set the C0_Compare register from a0
+ *
+ * Input parameters:
+ * a0 - compare register
+ *
+ * Return value:
+ * none
+ ********************************************************************* */
+
+LEAF(_setalarm)
+
+ mtc0 a0,C0_COMPARE
+ j ra
+END(_setalarm)
+
+
+/* *********************************************************************
+ * _SETCONTEXT()
+ *
+ * Set the CONTEXT register.
+ *
+ * Input parameters:
+ * a0 - context
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(_setcontext)
+
+ mtc0 a0,C0_CTEXT
+ j ra
+END(_setcontext)
+
+/* *********************************************************************
+ * _GETSEGTBL()
+ *
+ * Return the address of the segment table. We use this
+ * to display the startup messages.
+ *
+ * You can't just address the table from C because it lives
+ * in the text segment.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * address of table
+ ********************************************************************* */
+
+
+LEAF(_getsegtbl)
+ move t0,ra
+ LOADREL(v0,segment_table)
+ move ra,t0
+ j ra
+END(_getsegtbl)
+
+
+/* *********************************************************************
+ * _wbflush()
+ *
+ * Flush the write buffer. This is probably not necessary
+ * on SiByte CPUs, but we have it for completeness.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(_wbflush)
+
+ sync /* drain the buffers */
+ la t0,__junk /* do an uncached read to force it out */
+ or t0,K1BASE
+ lw zero,0(t0)
+ j ra
+
+END(_wbflush)
+
+
+/* *********************************************************************
+ * End
+ ********************************************************************* */
+
+
diff --git a/cfe/cfe/arch/mips/common/src/lib_hssubr.S b/cfe/cfe/arch/mips/common/src/lib_hssubr.S
new file mode 100644
index 0000000..07085e3
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/lib_hssubr.S
@@ -0,0 +1,194 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Hyperspace Subroutines File: lib_hssubr.S
+ *
+ * Little stub routines to allow access to KXSEG from 32-bit progs.
+ *
+ * Author: Mitch Lichtenberg (mitch@sibyte.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "sbmips.h"
+#include "mipsmacros.h"
+#include "cpu_config.h" /* for definition of HAZARD */
+
+
+/* *********************************************************************
+ * hs_read8 - read 8-bit bytes
+ ********************************************************************* */
+
+
+LEAF(hs_read8)
+ mfc0 t2,C0_SR
+ or t1,t2,M_SR_KX
+ mtc0 t1,C0_SR
+ HAZARD
+
+ lbu v0,(a0)
+
+ mtc0 t2,C0_SR
+ HAZARD
+ j ra
+END(hs_read8)
+
+/* *********************************************************************
+ * hs_read16 - read 16-bit shorts
+ ********************************************************************* */
+
+LEAF(hs_read16)
+ mfc0 t2,C0_SR
+ or t1,t2,M_SR_KX
+ mtc0 t1,C0_SR
+ HAZARD
+
+ lhu v0,(a0)
+
+ mtc0 t2,C0_SR
+ HAZARD
+ j ra
+END(hs_read16)
+
+/* *********************************************************************
+ * hs_read32 - read 32-bit ints
+ ********************************************************************* */
+
+LEAF(hs_read32)
+ mfc0 t2,C0_SR
+ or t1,t2,M_SR_KX
+ mtc0 t1,C0_SR
+ HAZARD
+
+ lw v0,(a0)
+
+ mtc0 t2,C0_SR
+ HAZARD
+ j ra
+END(hs_read32)
+
+/* *********************************************************************
+ * hs_read64 - read 64-bit longs
+ ********************************************************************* */
+
+LEAF(hs_read64)
+ mfc0 t2,C0_SR
+ or t1,t2,M_SR_KX
+ mtc0 t1,C0_SR
+ HAZARD
+
+ ld v0,(a0)
+
+ mtc0 t2,C0_SR
+ HAZARD
+ j ra
+END(hs_read64)
+
+/* *********************************************************************
+ * hs_write8 - write 8-bit bytes
+ ********************************************************************* */
+
+LEAF(hs_write8)
+ mfc0 t2,C0_SR
+ or t1,t2,M_SR_KX
+ mtc0 t1,C0_SR
+ HAZARD
+
+ sb a1,(a0)
+
+ mtc0 t2,C0_SR
+ HAZARD
+ j ra
+END(hs_write8)
+
+/* *********************************************************************
+ * hs_write16 - write 16-bit shorts
+ ********************************************************************* */
+
+LEAF(hs_write16)
+ mfc0 t2,C0_SR
+ or t1,t2,M_SR_KX
+ mtc0 t1,C0_SR
+ HAZARD
+
+ sh a1,(a0)
+
+ mtc0 t2,C0_SR
+ HAZARD
+ j ra
+END(hs_write16)
+
+/* *********************************************************************
+ * hs_write32 - write 32-bit longs
+ ********************************************************************* */
+
+LEAF(hs_write32)
+ mfc0 t2,C0_SR
+ or t1,t2,M_SR_KX
+ mtc0 t1,C0_SR
+ HAZARD
+
+ sw a1,(a0)
+
+ mtc0 t2,C0_SR
+ HAZARD
+ j ra
+END(hs_write32)
+
+/* *********************************************************************
+ * hs_write64 - write 64-bit longs
+ ********************************************************************* */
+
+LEAF(hs_write64)
+ mfc0 t2,C0_SR
+ or t1,t2,M_SR_KX
+ mtc0 t1,C0_SR
+ HAZARD
+
+ sd a1,(a0)
+
+ mtc0 t2,C0_SR
+ HAZARD
+ j ra
+END(hs_write64)
+
+
+/* *********************************************************************
+ * End
+ ********************************************************************* */
+
diff --git a/cfe/cfe/arch/mips/common/src/lib_physio.S b/cfe/cfe/arch/mips/common/src/lib_physio.S
new file mode 100644
index 0000000..7f57fea
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/lib_physio.S
@@ -0,0 +1,173 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Physical memory peek/poke routines File: lib_physio.S
+ *
+ * Little stub routines to allow access to arbitrary physical
+ * addresses. In most cases this should not be needed, as
+ * many physical addresses are within kseg1, but this handles
+ * the cases that are not automagically, so we don't need
+ * to mess up the code with icky macros and such.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "sbmips.h"
+#include "mipsmacros.h"
+#include "cpu_config.h" /* for definition of HAZARD */
+
+
+/* *********************************************************************
+ * PHYSOP(inst,a)
+ *
+ * Macro to construct code for doing the physical I/O
+ * We try to avoid messing with KX or doing 64-bit stuff
+ * unless necessary.
+ *
+ * Input parameters:
+ * INST - instruction name to run
+ * A - register containing arg or return value
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+
+#ifdef _MIPSREGS32_
+#define PHYSOP(INST,A) \
+ or a0,a0,K1BASE ; \
+ INST A,0(a0) ; \
+ j ra ;
+#else
+#define PHYSOP(INST,A) \
+ lui t0,0x2000 ; \
+ bgeu a0,t0,1f ; \
+ or a0,a0,K1BASE ; \
+ INST A,0(a0) ; \
+ j ra ; \
+1: lui t0,0x9000 ; \
+ dsll t0,t0,32 ; \
+ or a0,a0,t0 ; \
+ mfc0 t1,C0_SR ; \
+ and t0,t1,M_SR_KX ; \
+ beq t0,zero,1f ; \
+ INST A,0(a0) ; \
+ j ra ; \
+1: or t0,t1,M_SR_KX ; \
+ mtc0 t0,C0_SR ; \
+ HAZARD ; \
+ INST A,0(a0) ; \
+ mtc0 t1,C0_SR ; \
+ HAZARD ; \
+ j ra ;
+#endif
+
+
+/* *********************************************************************
+ * phys_read8 - read 8-bit bytes
+ ********************************************************************* */
+
+
+LEAF(phys_read8)
+PHYSOP(lbu,v0)
+END(phys_read8)
+
+/* *********************************************************************
+ * phys_read16 - read 16-bit shorts
+ ********************************************************************* */
+
+LEAF(phys_read16)
+PHYSOP(lh,v0)
+END(phys_read16)
+
+/* *********************************************************************
+ * phys_read32 - read 32-bit ints
+ ********************************************************************* */
+
+LEAF(phys_read32)
+PHYSOP(lw,v0)
+END(phys_read32)
+
+/* *********************************************************************
+ * phys_read64 - read 64-bit longs
+ ********************************************************************* */
+
+LEAF(phys_read64)
+PHYSOP(ld,v0)
+END(phys_read64)
+
+/* *********************************************************************
+ * phys_write8 - write 8-bit bytes
+ ********************************************************************* */
+
+LEAF(phys_write8)
+PHYSOP(sb,a1)
+END(phys_write8)
+
+/* *********************************************************************
+ * phys_write16 - write 16-bit shorts
+ ********************************************************************* */
+
+LEAF(phys_write16)
+PHYSOP(sh,a1)
+END(phys_write16)
+
+/* *********************************************************************
+ * phys_write32 - write 32-bit longs
+ ********************************************************************* */
+
+LEAF(phys_write32)
+PHYSOP(sw,a1)
+END(phys_write32)
+
+/* *********************************************************************
+ * phys_write64 - write 64-bit longs
+ ********************************************************************* */
+
+LEAF(phys_write64)
+PHYSOP(sd,a1)
+END(phys_write64)
+
+
+/* *********************************************************************
+ * End
+ ********************************************************************* */
+
diff --git a/cfe/cfe/arch/mips/common/src/lib_setjmp.S b/cfe/cfe/arch/mips/common/src/lib_setjmp.S
new file mode 100644
index 0000000..b8c82b3
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/lib_setjmp.S
@@ -0,0 +1,94 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Simple setjmp/longjmp File: lib_setjmp.S
+ *
+ * A very simple SETJMP and LONGJMP
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+
+#include "sbmips.h"
+#include "lib_setjmp.h"
+
+#ifdef _MIPSREGS32_
+#define SREG sw
+#define LREG lw
+#else
+#define SREG sd
+#define LREG ld
+#endif
+
+LEAF(lib_setjmp)
+
+ SREG s0,JMPB_S0(a0)
+ SREG s1,JMPB_S1(a0)
+ SREG s2,JMPB_S2(a0)
+ SREG s3,JMPB_S3(a0)
+ SREG s4,JMPB_S4(a0)
+ SREG s5,JMPB_S5(a0)
+ SREG s6,JMPB_S6(a0)
+ SREG s7,JMPB_S7(a0)
+ SREG fp,JMPB_FP(a0)
+ SREG sp,JMPB_SP(a0)
+ SREG ra,JMPB_RA(a0)
+ move v0,zero
+ j ra
+
+END(lib_setjmp)
+
+LEAF(lib_longjmp)
+ LREG s0,JMPB_S0(a0)
+ LREG s1,JMPB_S1(a0)
+ LREG s2,JMPB_S2(a0)
+ LREG s3,JMPB_S3(a0)
+ LREG s4,JMPB_S4(a0)
+ LREG s5,JMPB_S5(a0)
+ LREG s6,JMPB_S6(a0)
+ LREG s7,JMPB_S7(a0)
+ LREG fp,JMPB_FP(a0)
+ LREG sp,JMPB_SP(a0)
+ LREG ra,JMPB_RA(a0)
+ move v0,a1
+ jr ra
+END(lib_longjmp)
+
diff --git a/cfe/cfe/arch/mips/common/src/mips_arena.c b/cfe/cfe/arch/mips/common/src/mips_arena.c
new file mode 100644
index 0000000..d96fee6
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/mips_arena.c
@@ -0,0 +1,186 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Physical Memory (arena) manager File: sb1250_arena.c
+ *
+ * This module describes the physical memory available to the
+ * firmware.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "lib_arena.h"
+
+#include "cfe_error.h"
+
+#include "cfe.h"
+#include "cfe_mem.h"
+
+#include "initdata.h"
+
+#define _NOPROTOS_
+#include "cfe_boot.h"
+#undef _NOPROTOS_
+
+#include "cpu_config.h"
+
+#include "addrspace.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+
+#define MEG (1024*1024)
+#define KB 1024
+#define PAGESIZE 4096
+#define CFE_BOOTAREA_SIZE (256*KB)
+#define CFE_BOOTAREA_ADDR 0x20000000
+
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+extern arena_t cfe_arena;
+uint64_t *cfe_pagetable = NULL;
+
+extern void CPUCFG_PAGETBLINIT(uint64_t *ptaddr,unsigned int ptstart);
+
+void cfe_bootarea_init(void);
+extern void _setcontext(int64_t);
+
+
+/* *********************************************************************
+ * CFE_BOOTAREA_INIT()
+ *
+ * Initialize the page table and map our boot program area.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_bootarea_init(void)
+{
+ unsigned char *pte;
+ int64_t pte_int;
+ unsigned int addr = 16*MEG;
+ unsigned int topmem;
+ unsigned int topcfe;
+ unsigned int botcfe;
+ unsigned int beforecfe;
+ unsigned int aftercfe;
+
+ /*
+ * Calculate the location where the boot area will
+ * live. It lives either above or below the
+ * firmware, depending on where there's more space.
+ */
+
+ /*
+ * The firmware will always be loaded in the first
+ * 256M. Calculate the top of that region. The bottom
+ * of that region is always the beginning of our
+ * data segment.
+ */
+ if (mem_totalsize > (uint64_t)256) {
+ topmem = 256*MEG;
+ }
+ else {
+ topmem = (unsigned int) (mem_totalsize << 20);
+ }
+ botcfe = (unsigned int) K1_TO_PHYS(mem_bottomofmem);
+ topcfe = (unsigned int) K1_TO_PHYS(mem_topofmem);
+
+ beforecfe = botcfe;
+ aftercfe = topmem-topcfe;
+
+ if (beforecfe > aftercfe) {
+ botcfe -= (PAGESIZE-1);
+ botcfe &= ~(PAGESIZE-1); /* round down to page boundary */
+ addr = botcfe - CFE_BOOTAREA_SIZE; /* this is the address */
+ }
+ else {
+ topcfe += (PAGESIZE-1); /* round *up* to a page address */
+ topcfe &= ~(PAGESIZE-1);
+ addr = topcfe;
+ }
+
+ mem_bootarea_start = addr;
+ mem_bootarea_size = CFE_BOOTAREA_SIZE;
+
+ /*
+ * Allocate the page table
+ */
+
+ pte = KMALLOC(1024,1024);
+
+#ifdef __long64
+ pte_int = (int64_t) pte;
+#else
+ pte_int = (int64_t) ((int) pte);
+#endif
+
+ /*
+ * Set the CP0 CONTEXT register to point at the page table
+ */
+
+ pte_int <<= 13;
+ cfe_pagetable = (uint64_t *) pte;
+
+ _setcontext(pte_int);
+
+
+ /*
+ * Initialize page table entries
+ */
+
+ CPUCFG_PAGETBLINIT(cfe_pagetable,addr);
+
+
+}
+
diff --git a/cfe/cfe/arch/mips/common/src/tools.mk b/cfe/cfe/arch/mips/common/src/tools.mk
new file mode 100755
index 0000000..d195de9
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/tools.mk
@@ -0,0 +1,83 @@
+#
+# Basic compiler options and preprocessor flags
+#
+
+CFLAGS += -g -c -ffreestanding
+CFLAGS += -O1 -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
+
+#
+# Tools locations
+#
+
+ifndef TOOLS
+TOOLS=/opt/toolchains/uclibc-crosstools-gcc-4.4.2-1/usr/bin/mips-linux-
+endif
+
+GCC ?= $(TOOLS)gcc
+GLD ?= $(TOOLS)ld
+AR ?= $(TOOLS)ar
+OBJDUMP ?= $(TOOLS)objdump
+OBJCOPY ?= $(TOOLS)objcopy
+RANLIB ?= $(TOOLS)ranlib
+
+#
+# Check for 64-bit mode
+#
+
+ifeq ($(strip ${CFG_MLONG64}),1)
+ CFLAGS += -mlong64 -D__long64
+endif
+
+#
+# Figure out which linker script to use
+#
+
+ifeq ($(strip ${CFG_RAMAPP}),1)
+ CFLAGS += -DCFG_RAMAPP=1
+ LDFLAGS = -g --script ${ARCH_SRC}/cfe_ramapp.lds
+ CFLAGS += -DCFG_RUNFROMKSEG0=1
+else
+ ifeq ($(strip ${CFG_RELOC}),0)
+ ifeq ($(strip ${CFG_BOOTRAM}),1)
+ CFLAGS += -DCFG_BOOTRAM=1
+ ROMRAM = ram
+ else
+ CFLAGS += -DCFG_BOOTRAM=0
+ ROMRAM = rom
+ endif
+ ifeq ($(strip ${CFG_UNCACHED}),1)
+ CFLAGS += -DCFG_RUNFROMKSEG0=0
+ LDFLAGS = -g --script ${ARCH_SRC}/cfe_${ROMRAM}_uncached.lds
+ else
+ CFLAGS += -DCFG_RUNFROMKSEG0=1
+ LDFLAGS = -g --script ${ARCH_SRC}/cfe_${ROMRAM}_cached.lds
+ endif
+ else
+ CFLAGS += -membedded-pic -mlong-calls -DCFG_EMBEDDED_PIC=1
+ ifeq ($(strip ${CFG_UNCACHED}),1)
+ CFLAGS += -DCFG_RUNFROMKSEG0=0
+ LDFLAGS = -g --script ${ARCH_SRC}/cfe_rom_reloc_uncached.lds --embedded-relocs
+ else
+ CFLAGS += -DCFG_RUNFROMKSEG0=1
+ ifeq ($(strip ${CFG_TEXTAT1MB}),1)
+ LDFLAGS = -g --script ${ARCH_SRC}/cfe_rom_reloc_cached_biendian.lds --embedded-relocs
+ else
+ LDFLAGS = -g --script ${ARCH_SRC}/cfe_rom_reloc_cached.lds --embedded-relocs
+ endif
+ endif
+ endif
+endif
+#
+# Determine target endianness
+#
+
+ifeq ($(strip ${CFG_LITTLE}),1)
+ ENDIAN = -EL
+ CFLAGS += -EL
+ LDFLAGS += -EL
+else
+ ENDIAN = -EB
+ CFLAGS += -EB
+ LDFLAGS += -EB
+endif
+
diff --git a/cfe/cfe/arch/mips/common/src/ui_memtest.c b/cfe/cfe/arch/mips/common/src/ui_memtest.c
new file mode 100644
index 0000000..5388fd8
--- /dev/null
+++ b/cfe/cfe/arch/mips/common/src/ui_memtest.c
@@ -0,0 +1,282 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Test commands File: ui_memtest.c
+ *
+ * A simple memory test
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "sbmips.h"
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_devfuncs.h"
+
+#include "cfe_error.h"
+
+#include "ui_command.h"
+#include "cfe.h"
+
+#include "bsp_config.h"
+
+#include "cfe_mem.h"
+
+
+#ifdef __long64
+static int ui_cmd_memorytest(ui_cmdline_t *cmd,int argc,char *argv[]);
+#endif
+
+#ifndef _SB_MAKE64
+#define _SB_MAKE64(x) ((uint64_t)(x))
+#endif
+#ifndef _SB_MAKEMASK
+#define _SB_MAKEMASK(v,n) (_SB_MAKE64((_SB_MAKE64(1)<<(v))-1) << _SB_MAKE64(n))
+#endif
+#ifndef _SB_MAKEMASK1
+#define _SB_MAKEMASK1(n) (_SB_MAKE64(1) << _SB_MAKE64(n))
+#endif
+
+
+int ui_init_memtestcmds(void);
+
+int ui_init_memtestcmds(void)
+{
+#ifdef __long64
+ cmd_addcmd("memorytest",
+ ui_cmd_memorytest,
+ NULL,
+ "Tests all available memory",
+ "",
+ "-loop;Loop forever or until keypress|"
+ "-stoponerror;Stop if error occurs while looping|"
+ "-cca=*;Use specified cacheability attribute|"
+ "-arena=*;Test only specified arena index");
+#endif
+ return 0;
+}
+
+
+#ifdef __long64
+/* extensive memory tests */
+
+static void inline uacwrite(volatile long *srcadr,long *dstadr)
+{
+__asm __volatile ("ld $8, 0(%0) ; "
+ "ld $9, 8(%0) ; "
+ "ld $10, 16(%0) ; "
+ "ld $11, 24(%0) ; "
+ "sync ; "
+ "sd $8, 0(%1) ; "
+ "sd $9, 8(%1) ; "
+ "sd $10, 16(%1) ; "
+ "sd $11, 24(%1) ; "
+ "sync" :: "r"(srcadr),"r"(dstadr) : "$8","$9","$10","$11");
+}
+
+
+#define TEST_DATA_LEN 4
+#define CACHE_LINE_LEN 32
+
+static int ui_cmd_memorytest(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+
+ static volatile long test_data[TEST_DATA_LEN] = {
+ 0xaaaaaaaaaaaaaaaa, 0x5555555555555555, 0xcccccccccccccccc, 0x3333333333333333, /* one cache line */
+ };
+ int arena, exitLoop;
+ int error;
+ int arena_type;
+ uint64_t arena_start, arena_size;
+ long phys_addr, offset, mem_base, cache_mem_base, i;
+ long *dst_adr, *cache_dst_adr;
+ long cda,tda;
+ int forever;
+ int passcnt;
+ int stoponerr = 0;
+ int cca = K_CALG_UNCACHED_ACCEL;
+ int arenanum = -1;
+ char *x;
+
+ arena = 0;
+ exitLoop = 0;
+ offset = 0;
+ mem_base = 0;
+ passcnt = 0;
+ error = 0;
+
+ forever = cmd_sw_isset(cmd,"-loop");
+ stoponerr = cmd_sw_isset(cmd,"-stoponerror");
+ if (cmd_sw_value(cmd,"-cca",&x)) cca = atoi(x);
+ if (cmd_sw_value(cmd,"-arena",&x)) arenanum = atoi(x);
+
+ printf("Available memory arenas:\n");
+ while (cfe_arena_enum(arena, &arena_type, &arena_start, &arena_size, FALSE) == 0) {
+ phys_addr = (long) arena_start; /* actual physical address */
+ mem_base = PHYS_TO_XKPHYS(cca, phys_addr); /* virtual address */
+ xprintf("phys = %016llX, virt = %016llX, size = %016llX\n", phys_addr, mem_base, arena_size);
+ arena++;
+ }
+
+ printf("\nTesting memory.\n");
+ do {
+
+ passcnt++;
+ if (forever) {
+ if (console_status()) break;
+ printf("***** Iteration %d *****\n",passcnt);
+ }
+
+ arena = 0;
+ exitLoop = 0;
+ error = 0;
+
+ while (cfe_arena_enum(arena, &arena_type, &arena_start, &arena_size, FALSE) == 0) {
+
+ if ((arenanum >= 0) && (arena != arenanum)) {
+ arena++;
+ continue;
+ }
+
+ test_data[0] = 0xAAAAAAAAAAAAAAAA;
+ test_data[1] = 0x5555555555555555;
+ test_data[2] = 0xCCCCCCCCCCCCCCCC;
+ test_data[3] = 0x3333333333333333;
+
+ phys_addr = (long) arena_start; /* actual physical address */
+ mem_base = PHYS_TO_XKPHYS(cca, phys_addr); /* virtual address */
+ cache_mem_base = PHYS_TO_K0(phys_addr);
+
+ xprintf("\n");
+ xprintf("Testing: phys = %016llX, virt = %016llX, size = %016llX\n", phys_addr, mem_base, arena_size);
+
+ xprintf("Writing: a/5/c/3\n");
+
+ for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) {
+ dst_adr = (long*)(mem_base+offset);
+ uacwrite(test_data, dst_adr);
+ }
+
+ xprintf("Reading: a/5/c/3\n");
+
+ for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) {
+ dst_adr = (long*)(mem_base+offset);
+ cache_dst_adr = (long*)(mem_base+offset);
+ for (i = 0; i < TEST_DATA_LEN; i++) {
+ cda = cache_dst_adr[i];
+ tda = test_data[i];
+ if (cda != tda) {
+ xprintf("mem[%016llX] %016llX != %016llX\n",
+ mem_base+offset+(i*8), cda, tda);
+ exitLoop = 1;
+ }
+ }
+ if (exitLoop) break;
+ }
+
+
+ if (exitLoop) {
+ exitLoop = 0;
+ error++;
+ arena++;
+ continue;
+ }
+
+ xprintf("Writing: address|5555/inv/aaaa|address\n");
+ exitLoop = 0;
+
+ for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) {
+ dst_adr = (long*)(mem_base+offset);
+ test_data[0] = ((long)dst_adr<<32)|0x55555555;
+ test_data[1] = ~test_data[0];
+ test_data[2] = 0xaaaaaaaa00000000|((long)dst_adr & 0xffffffff);
+ test_data[3] = ~test_data[2];
+ uacwrite(test_data, dst_adr);
+ }
+
+ xprintf("Reading: address|5555/inv/aaaa|address\n");
+
+ for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) {
+ dst_adr = (long*)(mem_base+offset);
+ test_data[0] = ((long)dst_adr<<32)|0x55555555;
+ test_data[1] = ~test_data[0];
+ test_data[2] = 0xaaaaaaaa00000000|((long)dst_adr & 0xffffffff);
+ test_data[3] = ~test_data[2];
+ cache_dst_adr = (long*)(mem_base+offset);
+ for (i = 0; i < TEST_DATA_LEN; i++) {
+ cda = cache_dst_adr[i];
+ tda = test_data[i];
+ if (cda != tda) {
+ xprintf("mem[%016llX] %016llX != %016llX\n",
+ mem_base+offset+(i*8),cda,tda);
+ exitLoop = 1;
+ }
+ }
+ if (exitLoop) break;
+ }
+
+ if (exitLoop) {
+ error++;
+ exitLoop = 0;
+ if (stoponerr) forever = 0;
+ }
+
+ arena++;
+ }
+ } while (forever);
+
+ if (error) printf("Failing address: %016llX\n",mem_base+offset);
+
+ return error ? -1 : 0;
+}
+
+#endif
+
+
+
+
diff --git a/cfe/cfe/arch/mips/cpu/SIBYTE_PRIVATE_FILES b/cfe/cfe/arch/mips/cpu/SIBYTE_PRIVATE_FILES
new file mode 100644
index 0000000..1e7d4b6
--- /dev/null
+++ b/cfe/cfe/arch/mips/cpu/SIBYTE_PRIVATE_FILES
@@ -0,0 +1,2 @@
+bcmcore
+bcm1400
diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/include/bcm4710.h b/cfe/cfe/arch/mips/cpu/bcmcore/include/bcm4710.h
new file mode 100644
index 0000000..f499bc9
--- /dev/null
+++ b/cfe/cfe/arch/mips/cpu/bcmcore/include/bcm4710.h
@@ -0,0 +1,58 @@
+/*
+ Copyright 2001, Broadcom Corporation
+ All Rights Reserved.
+
+ This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ the contents of this file may not be disclosed to third parties, copied or
+ duplicated in any form, in whole or in part, without the prior written
+ permission of Broadcom Corporation.
+*/
+/*
+ * BCM4710 address space map and definitions
+ *
+ * Think twice before adding to this file, this is not the kitchen sink
+ * These definitions are not guaranteed for all 47xx chips, only the 4710
+ *
+ * Copyright (C) 2000 Broadcom Corporation
+ * $Id: bcm4710.h,v 1.1 2001/10/31 18:49:25 mpl Exp $
+ */
+
+#ifndef _bcm4710_h_
+#define _bcm4710_h_
+
+/* Address map */
+#define BCM4710_SDRAM 0x00000000 /* Physical SDRAM */
+#define BCM4710_PCI_MEM 0x08000000 /* Host Mode PCI memory access space (64 MB) */
+#define BCM4710_PCI_CFG 0x0c000000 /* Host Mode PCI configuration space (64 MB) */
+#define BCM4710_PCI_DMA 0x40000000 /* Client Mode PCI memory access space (1 GB) */
+#define BCM4710_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */
+#define BCM4710_ENUM 0x18000000 /* Beginning of core enumeration space */
+
+/* Core register space */
+#define BCM4710_REG_SDRAM 0x18000000 /* SDRAM core registers */
+#define BCM4710_REG_ILINE20 0x18001000 /* InsideLine20 core registers */
+#define BCM4710_REG_EMAC0 0x18002000 /* Ethernet MAC 0 core registers */
+#define BCM4710_REG_CODEC 0x18003000 /* Codec core registers */
+#define BCM4710_REG_USB 0x18004000 /* USB core registers */
+#define BCM4710_REG_PCI 0x18005000 /* PCI core registers */
+#define BCM4710_REG_MIPS 0x18006000 /* MIPS core registers */
+#define BCM4710_REG_EXTIF 0x18007000 /* External Interface core registers */
+#define BCM4710_REG_EMAC1 0x18008000 /* Ethernet MAC 1 core registers */
+
+#define BCM4710_EXTIF 0x1f000000 /* External Interface base address */
+#define BCM4710_EJTAG 0xff200000 /* MIPS EJTAG space (2M) */
+
+#define BCM4710_UART (BCM4710_REG_EXTIF + 0x00000300)
+
+#define BCM4710_EUART (BCM4710_EXTIF + 0x00800000)
+#define BCM4710_LED (BCM4710_EXTIF + 0x00900000)
+
+#ifdef CONFIG_VSIM
+#define BCM4710_TRACE(trval) do { *((int *)0xa0002ff8) = (trval); } while (0)
+#else
+#define BCM4710_TRACE(trval) do { *((unsigned char *)KSEG1ADDR(BCM4710_LED)) = (trval); \
+ *((int *)0xa0002ff8) = (trval); } while (0)
+#endif
+
+
+#endif /* _bcm4710_h_ */
diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/include/bcm47xx.h b/cfe/cfe/arch/mips/cpu/bcmcore/include/bcm47xx.h
new file mode 100644
index 0000000..eb752e5
--- /dev/null
+++ b/cfe/cfe/arch/mips/cpu/bcmcore/include/bcm47xx.h
@@ -0,0 +1,8 @@
+#ifndef _BCM47XX_H
+#define _BCM47XX_H
+
+/* uart defaults */
+#define DIV_LO 0x36
+#define DIV_HI 0
+
+#endif
diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/include/bcmnvram.h b/cfe/cfe/arch/mips/cpu/bcmcore/include/bcmnvram.h
new file mode 100644
index 0000000..b9d37e6
--- /dev/null
+++ b/cfe/cfe/arch/mips/cpu/bcmcore/include/bcmnvram.h
@@ -0,0 +1,123 @@
+/*
+ Copyright 2001, Broadcom Corporation
+ All Rights Reserved.
+
+ This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ the contents of this file may not be disclosed to third parties, copied or
+ duplicated in any form, in whole or in part, without the prior written
+ permission of Broadcom Corporation.
+*/
+/*
+ * NVRAM variable manipulation
+ *
+ * Copyright (C) 2001 Broadcom Corporation
+ *
+ * $Id: bcmnvram.h,v 1.1 2001/10/31 18:49:25 mpl Exp $
+ */
+
+#ifndef _bcmnvram_h_
+#define _bcmnvram_h_
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+struct nvram_header {
+ unsigned long magic;
+ unsigned long len;
+ unsigned long crc_ver_init; /* 0:7 crc, 8:15 ver, 16:27 init, mem. test 28, 29-31 reserved */
+ unsigned long config_refresh; /* 0:15 config, 16:31 refresh */
+ unsigned long reserved;
+};
+
+struct nvram_tuple {
+ char *name;
+ char *value;
+ struct nvram_tuple *next;
+};
+
+/* Compatibility */
+typedef struct nvram_tuple EnvRec;
+
+/*
+ * Get the value of an NVRAM variable
+ * @param name name of variable to get
+ * @return value of variable or NULL if undefined
+ */
+extern char * nvram_get(const char *name);
+
+/*
+ * Get the value of an NVRAM variable
+ * @param name name of variable to get
+ * @return value of variable or NUL if undefined
+ */
+#define nvram_safe_get(name) (nvram_get(name) ? : "")
+
+/*
+ * Match an NVRAM variable
+ * @param name name of variable to match
+ * @param match value to compare against value of variable
+ * @return TRUE if variable is defined and its value is string equal to match or FALSE otherwise
+ */
+#define nvram_match(name, match) ({ \
+ const char *value = nvram_get(name); \
+ (value && !strcmp(value, match)); \
+})
+
+/*
+ * Match an NVRAM variable
+ * @param name name of variable to match
+ * @param match value to compare against value of variable
+ * @return TRUE if variable is defined and its value is not string equal to invmatch or FALSE otherwise
+ */
+#define nvram_invmatch(name, invmatch) ({ \
+ const char *value = nvram_get(name); \
+ (value && strcmp(value, invmatch)); \
+})
+
+/*
+ * Set the value of an NVRAM variable
+ * @param name name of variable to set
+ * @param value value of variable
+ * @return 0 on success and errno on failure
+ * NOTE: use nvram_commit to commit this change to flash.
+ */
+extern int nvram_set(const char *name, const char *value);
+
+/*
+ * Unset an NVRAM variable
+ * @param name name of variable to unset
+ * @return 0 on success and errno on failure
+ * NOTE: use nvram_commit to commit this change to flash.
+ */
+extern int nvram_unset(const char *name);
+
+/*
+ * Permanently commit NVRAM variables
+ * @return 0 on success and errno on failure
+ */
+extern int nvram_commit(void);
+
+/*
+ * Get all NVRAM variables (format name=value\0 ... \0\0)
+ * @param buf buffer to store variables
+ * @param count size of buffer in bytes
+ * @return 0 on success and errno on failure
+ */
+extern int nvram_getall(char *buf, int count);
+
+/*
+ * Invalidate the current NVRAM header
+ * @return 0 on success and errno on failure
+ */
+extern int nvram_invalidate(void);
+
+#endif /* _LANGUAGE_ASSEMBLY */
+
+#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */
+#define NVRAM_VERSION 1
+#define NVRAM_HEADER_SIZE 20
+#define NVRAM_FIRST_LOC 0xbfcf8000
+#define NVRAM_LAST_LOC 0xbfff8000
+#define NVRAM_LOC_GAP 0x100000
+#define NVRAM_SPACE 0x8000
+
+#endif /* _bcmnvram_h_ */
diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/include/cpu_config.h b/cfe/cfe/arch/mips/cpu/bcmcore/include/cpu_config.h
new file mode 100755
index 0000000..51cf4e1
--- /dev/null
+++ b/cfe/cfe/arch/mips/cpu/bcmcore/include/cpu_config.h
@@ -0,0 +1,62 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * CPU Configuration file File: cpu_config.h
+ *
+ * This file contains the names of the routines to be used
+ * in the dispatch table in init_mips.S
+ *
+ * It lives here in the CPU directory so we can direct
+ * the init calls to routines named in this directory.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * XX Copyright 2000,2001
+ * Broadcom Corporation. All rights reserved.
+ *
+ * BROADCOM PROPRIETARY AND CONFIDENTIAL
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the license.
+ ********************************************************************* */
+
+/*
+ */
+
+#define CPUCFG_CPUINIT bcmcore_cpuinit
+#define CPUCFG_ALTCPU_START1 bcmcore_null
+#define CPUCFG_ALTCPU_START2 bcmcore_null
+#define CPUCFG_ALTCPU_RESET bcmcore_null
+#define CPUCFG_CPURESTART bcmcore_cpurestart
+#define CPUCFG_DRAMINIT board_draminit /* no dram on CPU */
+#define CPUCFG_CACHEOPS bcmcore_cacheops
+#define CPUCFG_ARENAINIT bcmcore_arena_init
+#define CPUCFG_PAGETBLINIT bcmcore_pagetable_init
+#define CPUCFG_TLBHANDLER bcmcore_tlbhandler
+#define CPUCFG_DIAG_TEST1 bcmcore_null
+#define CPUCFG_DIAG_TEST2 bcmcore_null
+#if CFG_CMT
+#define CPUCFG_TP1_SWITCH bcmcore_tp1_switch
+#else
+#define CPUCFG_TP1_SWITCH bcmcore_null
+#endif
+/*
+ * The BCMCORE ticks CP0 every other cycle.
+ */
+
+#define CPUCFG_CYCLESPERCPUTICK 2
+
+/*
+ * Hazard macro
+ */
+
+#define HAZARD nop ; nop ; nop ; nop ; nop ; nop ; nop
+#define ERET \
+ .set push ; \
+ .set mips4 ; \
+ eret ; \
+ .set pop
+
+
diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/include/sbmips.h b/cfe/cfe/arch/mips/cpu/bcmcore/include/sbmips.h
new file mode 100644
index 0000000..0f4e055
--- /dev/null
+++ b/cfe/cfe/arch/mips/cpu/bcmcore/include/sbmips.h
@@ -0,0 +1,670 @@
+/* *********************************************************************
+ * SB1250 Board Support Package
+ *
+ * MIPS64 CPU definitions File: sbmips.h
+ *
+ * This module contains constants and macros specific to the
+ * SB1 MIPS64 core.
+ *
+ * Author: Mitch Lichtenberg (mitch@sibyte.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifndef _SB_MIPS_H
+#define _SB_MIPS_H
+
+/* *********************************************************************
+ * Configure language
+ ********************************************************************* */
+
+#if defined(__ASSEMBLER__)
+#define _ATYPE_
+#define _ATYPE32_
+#define _ATYPE64_
+#else
+#define _ATYPE_ (__SIZE_TYPE__)
+#define _ATYPE32_ (int)
+#define _ATYPE64_ (long long)
+#endif
+
+
+/* *********************************************************************
+ * Bitfield macros
+ ********************************************************************* */
+
+/*
+ * Make a mask for 1 bit at position 'n'
+ */
+
+#define _MM_MAKEMASK1(n) (1 << (n))
+
+/*
+ * Make a mask for 'v' bits at position 'n'
+ */
+
+#define _MM_MAKEMASK(v,n) (((1<<(v))-1) << (n))
+
+/*
+ * Make a value at 'v' at bit position 'n'
+ */
+
+#define _MM_MAKEVALUE(v,n) ((v) << (n))
+
+/*
+ * Retrieve a value from 'v' at bit position 'n' with 'm' mask bits
+ */
+
+#define _MM_GETVALUE(v,n,m) (((v) & (m)) >> (n))
+
+
+
+/* *********************************************************************
+ * 32-bit MIPS Address Spaces
+ ********************************************************************* */
+
+#ifdef __ASSEMBLER__
+#define _ACAST32_
+#define _ACAST64_
+#else
+#define _ACAST32_ _ATYPE_ _ATYPE32_ /* widen if necessary */
+#define _ACAST64_ _ATYPE64_ /* do _not_ narrow */
+#endif
+
+/* 32-bit address map */
+#define UBASE 0x00000000 /* user+ mapped */
+#define USIZE 0x80000000
+#define K0BASE (_ACAST32_ 0x80000000) /* kernel unmapped cached */
+#define K0SIZE 0x20000000
+#define K1BASE (_ACAST32_ 0xa0000000) /* kernel unmapped uncached */
+#define K1SIZE 0x20000000
+#define KSBASE (_ACAST32_ 0xc0000000) /* supervisor+ mapped */
+#define KSSIZE 0x20000000
+#define K3BASE (_ACAST32_ 0xe0000000) /* kernel mapped */
+#define K3SIZE 0x20000000
+
+/* 64-bit address map additions to the above (sign-extended) ranges */
+#define XUBASE (_ACAST64_ 0x0000000080000000) /* user+ mapped */
+#define XUSIZE (_ACAST64_ 0x00000FFF80000000)
+#define XSSEGBASE (_ACAST64_ 0x4000000000000000) /* supervisor+ mapped */
+#define XSSEGSIZE (_ACAST64_ 0x0000100000000000)
+#define XKPHYSBASE (_ACAST64_ 0x8000000000000000) /* kernel unmapped */
+#define XKPHYSSIZE (_ACAST64_ 0x0000100000000000)
+#define XKSEGBASE (_ACAST64_ 0xC000000000000000) /* kernel mapped */
+#define XKSEGSIZE (_ACAST64_ 0x00000FFF80000000)
+
+#define GEN_VECT (_ACAST32_ 0x80000080)
+#define UTLB_VECT (_ACAST32_ 0x80000000)
+
+/* *********************************************************************
+ * Address space coercion macros
+ ********************************************************************* */
+
+#define PHYS_TO_K0(pa) (K0BASE | (pa))
+#define PHYS_TO_K1(pa) (K1BASE | (pa))
+#define K0_TO_PHYS(va) ((va) & (K0SIZE-1))
+#define K1_TO_PHYS(va) ((va) & (K1SIZE-1))
+#define K0_TO_K1(va) ((va) | K1SIZE)
+#define K1_TO_K0(va) ((va) & ~K1SIZE)
+
+#define PHYS_TO_XK1(p) (_ACAST64_ (0xffffffffa0000000 | (p)))
+#define XK1_TO_PHYS(p) ((p) & (K1SIZE-1))
+#define PHYS_TO_XKPHYS(cca,p) (_SB_MAKEMASK1(63) | (_SB_MAKE64(cca) << 59) | (p))
+#define PHYS_TO_XKSEG_UNCACHED(p) PHYS_TO_XKPHYS(K_CALG_UNCACHED,(p))
+#define PHYS_TO_XKSEG_CACHED(p) PHYS_TO_XKPHYS(K_CALG_COH_SHAREABLE,(p))
+#define XKPHYS_TO_PHYS(p) ((p) & _SB_MAKEMASK(0,59))
+
+
+#if !defined(__ASSEMBLER__)
+#define mips_wbflush() __asm__ __volatile__ ("sync" : : : "memory")
+#define ISK0SEG(va) ((va) >= K0BASE && (va) <= (K0BASE + K0SIZE - 1))
+#define ISK1SEG(va) ((va) >= K1BASE && (va) <= (K1BASE + K1SIZE - 1))
+#endif
+
+/* *********************************************************************
+ * Register aliases
+ ********************************************************************* */
+
+#if defined(__ASSEMBLER__)
+#define zero $0
+#define AT $1 /* assembler temporaries */
+#define v0 $2 /* value holders */
+#define v1 $3
+#define a0 $4 /* arguments */
+#define a1 $5
+#define a2 $6
+#define a3 $7
+#define t0 $8 /* temporaries */
+#define t1 $9
+#define t2 $10
+#define t3 $11
+#define t4 $12
+#define t5 $13
+#define t6 $14
+#define t7 $15
+#define ta0 $12
+#define ta1 $13
+#define ta2 $14
+#define ta3 $15
+#define s0 $16 /* saved registers */
+#define s1 $17
+#define s2 $18
+#define s3 $19
+#define s4 $20
+#define s5 $21
+#define s6 $22
+#define s7 $23
+#define t8 $24 /* temporaries */
+#define t9 $25
+#define k0 $26 /* kernel registers */
+#define k1 $27
+#define gp $28 /* global pointer */
+#define sp $29 /* stack pointer */
+#define s8 $30 /* saved register */
+#define fp $30 /* frame pointer */
+#define ra $31 /* return address */
+#endif
+
+/* *********************************************************************
+ * CP0 Registers
+ ********************************************************************* */
+
+#if defined(__ASSEMBLER__)
+#define C0_INX $0 /* CP0: TLB Index */
+#define C0_RAND $1 /* CP0: TLB Random */
+#define C0_TLBLO0 $2 /* CP0: TLB EntryLo0 */
+#define C0_TLBLO C0_TLBLO0 /* CP0: TLB EntryLo0 */
+#define C0_TLBLO1 $3 /* CP0: TLB EntryLo1 */
+#define C0_CTEXT $4 /* CP0: Context */
+#define C0_PGMASK $5 /* CP0: TLB PageMask */
+#define C0_WIRED $6 /* CP0: TLB Wired */
+#define C0_BADVADDR $8 /* CP0: Bad Virtual Address */
+#define C0_COUNT $9 /* CP0: Count */
+#define C0_TLBHI $10 /* CP0: TLB EntryHi */
+#define C0_COMPARE $11 /* CP0: Compare */
+#define C0_SR $12 /* CP0: Processor Status */
+#define C0_STATUS C0_SR /* CP0: Processor Status */
+#define C0_CAUSE $13 /* CP0: Exception Cause */
+#define C0_EPC $14 /* CP0: Exception PC */
+#define C0_PRID $15 /* CP0: Processor Revision Indentifier */
+#define C0_CONFIG $16 /* CP0: Config */
+#define C0_LLADDR $17 /* CP0: LLAddr */
+#define C0_WATCHLO $18 /* CP0: WatchpointLo */
+#define C0_WATCHHI $19 /* CP0: WatchpointHi */
+#define C0_XCTEXT $20 /* CP0: XContext */
+#define C0_ECC $26 /* CP0: ECC */
+#define C0_CACHEERR $27 /* CP0: CacheErr */
+#define C0_TAGLO $28 /* CP0: TagLo */
+#define C0_TAGHI $29 /* CP0: TagHi */
+#define C0_ERREPC $30 /* CP0: ErrorEPC */
+#else
+#define C0_INX 0 /* CP0: TLB Index */
+#define C0_RAND 1 /* CP0: TLB Random */
+#define C0_TLBLO0 2 /* CP0: TLB EntryLo0 */
+#define C0_TLBLO C0_TLBLO0 /* CP0: TLB EntryLo0 */
+#define C0_TLBLO1 3 /* CP0: TLB EntryLo1 */
+#define C0_CTEXT 4 /* CP0: Context */
+#define C0_PGMASK 5 /* CP0: TLB PageMask */
+#define C0_WIRED 6 /* CP0: TLB Wired */
+#define C0_BADVADDR 8 /* CP0: Bad Virtual Address */
+#define C0_COUNT 9 /* CP0: Count */
+#define C0_TLBHI 10 /* CP0: TLB EntryHi */
+#define C0_COMPARE 11 /* CP0: Compare */
+#define C0_SR 12 /* CP0: Processor Status */
+#define C0_STATUS C0_SR /* CP0: Processor Status */
+#define C0_CAUSE 13 /* CP0: Exception Cause */
+#define C0_EPC 14 /* CP0: Exception PC */
+#define C0_PRID 15 /* CP0: Processor Revision Indentifier */
+#define C0_CONFIG 16 /* CP0: Config */
+#define C0_LLADDR 17 /* CP0: LLAddr */
+#define C0_WATCHLO 18 /* CP0: WatchpointLo */
+#define C0_WATCHHI 19 /* CP0: WatchpointHi */
+#define C0_XCTEXT 20 /* CP0: XContext */
+#define C0_ECC 26 /* CP0: ECC */
+#define C0_CACHEERR 27 /* CP0: CacheErr */
+#define C0_TAGLO 28 /* CP0: TagLo */
+#define C0_TAGHI 29 /* CP0: TagHi */
+#define C0_ERREPC 30 /* CP0: ErrorEPC */
+#endif
+
+/* *********************************************************************
+ * CP1 (floating point) control registers
+ ********************************************************************* */
+
+#define FPA_IRR 0 /* CP1: Implementation/Revision */
+#define FPA_CSR 31 /* CP1: Control/Status */
+
+/* *********************************************************************
+ * Macros for generating assembly language routines
+ ********************************************************************* */
+
+#if defined(__ASSEMBLER__)
+
+/* global leaf function (does not call other functions) */
+#define LEAF(name) \
+ .globl name; \
+ .ent name; \
+name:
+
+/* global alternate entry to (local or global) leaf function */
+#define XLEAF(name) \
+ .globl name; \
+ .aent name; \
+name:
+
+/* end of a global function */
+#define END(name) \
+ .size name,.-name; \
+ .end name
+
+/* local leaf function (does not call other functions) */
+#define SLEAF(name) \
+ .ent name; \
+name:
+
+/* local alternate entry to (local or global) leaf function */
+#define SXLEAF(name) \
+ .aent name; \
+name:
+
+/* end of a local function */
+#define SEND(name) \
+ END(name)
+
+/* define & export a symbol */
+#define EXPORT(name) \
+ .globl name; \
+name:
+
+/* import a symbol */
+#define IMPORT(name, size) \
+ .extern name,size
+
+/* define a zero-fill common block (BSS if not overridden) with a global name */
+#define COMM(name,size) \
+ .comm name,size
+
+/* define a zero-fill common block (BSS if not overridden) with a local name */
+#define LCOMM(name,size) \
+ .lcomm name,size
+
+#endif
+
+
+/* Floating-Point Control register bits */
+#define CSR_C 0x00800000
+#define CSR_EXC 0x0003f000
+#define CSR_EE 0x00020000
+#define CSR_EV 0x00010000
+#define CSR_EZ 0x00008000
+#define CSR_EO 0x00004000
+#define CSR_EU 0x00002000
+#define CSR_EI 0x00001000
+#define CSR_TV 0x00000800
+#define CSR_TZ 0x00000400
+#define CSR_TO 0x00000200
+#define CSR_TU 0x00000100
+#define CSR_TI 0x00000080
+#define CSR_SV 0x00000040
+#define CSR_SZ 0x00000020
+#define CSR_SO 0x00000010
+#define CSR_SU 0x00000008
+#define CSR_SI 0x00000004
+#define CSR_RM 0x00000003
+
+/* Status Register */
+#define M_SR_CUMASK _MM_MAKEMASK(4,28) /* coprocessor usable bits */
+#define M_SR_CU3 _MM_MAKEMASK1(31) /* coprocessor 3 usable */
+#define M_SR_CU2 _MM_MAKEMASK1(30) /* coprocessor 2 usable */
+#define M_SR_CU1 _MM_MAKEMASK1(29) /* coprocessor 1 usable */
+#define M_SR_CU0 _MM_MAKEMASK1(28) /* coprocessor 0 usable */
+
+#define M_SR_RP _MM_MAKEMASK1(27) /* reduced power mode */
+#define M_SR_FR _MM_MAKEMASK1(26) /* fpu regs any data */
+#define M_SR_RE _MM_MAKEMASK1(25) /* reverse endian */
+#define M_SR_MX _MM_MAKEMASK1(24) /* MDMX */
+#define M_SR_PX _MM_MAKEMASK1(23) /* 64-bit ops in user mode */
+#define M_SR_BEV _MM_MAKEMASK1(22) /* boot exception vectors */
+#define M_SR_TS _MM_MAKEMASK1(21) /* TLB is shut down */
+#define M_SR_SR _MM_MAKEMASK1(20) /* soft reset */
+#define M_SR_NMI _MM_MAKEMASK1(19) /* nonmaskable interrupt */
+
+#define M_SR_IMASK _MM_MAKEMASK(8,8) /* all interrupt mask bits */
+
+#define M_SR_IBIT8 _MM_MAKEMASK1(15) /* individual bits */
+#define M_SR_IBIT7 _MM_MAKEMASK1(14)
+#define M_SR_IBIT6 _MM_MAKEMASK1(13)
+#define M_SR_IBIT5 _MM_MAKEMASK1(12)
+#define M_SR_IBIT4 _MM_MAKEMASK1(11)
+#define M_SR_IBIT3 _MM_MAKEMASK1(10)
+#define M_SR_IBIT2 _MM_MAKEMASK1(9)
+#define M_SR_IBIT1 _MM_MAKEMASK1(8)
+
+#define M_SR_IMASK8 0 /* masks for nested int levels */
+#define M_SR_IMASK7 _MM_MAKEMASK(1,15)
+#define M_SR_IMASK6 _MM_MAKEMASK(2,14)
+#define M_SR_IMASK5 _MM_MAKEMASK(3,13)
+#define M_SR_IMASK4 _MM_MAKEMASK(4,12)
+#define M_SR_IMASK3 _MM_MAKEMASK(5,11)
+#define M_SR_IMASK2 _MM_MAKEMASK(6,10)
+#define M_SR_IMASK1 _MM_MAKEMASK(7,9)
+#define M_SR_IMASK0 _MM_MAKEMASK(8,8)
+
+#define M_SR_KX _MM_MAKEMASK1(7) /* 64-bit access for kernel */
+#define M_SR_SX _MM_MAKEMASK1(6) /* .. for supervisor */
+#define M_SR_UX _MM_MAKEMASK1(5) /* .. for user */
+
+#define S_SR_KSU 3 /* base operating mode mode */
+#define M_SR_KSU _MM_MAKEMASK(2,S_SR_KSU)
+#define V_SR_KSU(x) _MM_MAKEVALUE(x,S_SR_KSU)
+#define G_SR_KSU(x) _MM_GETVALUE(x,S_SR_KSU,M_SR_KSU)
+#define K_SR_KSU_KERNEL 0
+#define K_SR_KSU_SUPR 1
+#define K_SR_KSU_USER 2
+
+#define M_SR_UM _MM_MAKEMASK1(4)
+#define M_SR_ERL _MM_MAKEMASK1(2)
+#define M_SR_EXL _MM_MAKEMASK1(1)
+#define M_SR_IE _MM_MAKEMASK1(0)
+
+/*
+ * Cause Register
+ */
+#define M_CAUSE_BD _MM_MAKEMASK1(31) /* exception in BD slot */
+
+#define S_CAUSE_CE 28 /* coprocessor error */
+#define M_CAUSE_CE _MM_MAKEMASK(2,S_CAUSE_CE)
+#define V_CAUSE_CE(x) _MM_MAKEVALUE(x,S_CAUSE_CE)
+#define G_CAUSE_CE(x) _MM_GETVALUE(x,S_CAUSE_CE,M_CAUSE_CE)
+
+#define M_CAUSE_IV _MM_MAKEMASK1(23) /* special interrupt */
+#define M_CAUSE_WP _MM_MAKEMASK1(22) /* watch interrupt deferred */
+
+#define S_CAUSE_IPMASK 8
+#define M_CAUSE_IPMASK _MM_MAKEMASK(8,S_CAUSE_IPMASK)
+#define M_CAUSE_IP8 _MM_MAKEMASK1(15) /* hardware interrupts */
+#define M_CAUSE_IP7 _MM_MAKEMASK1(14)
+#define M_CAUSE_IP6 _MM_MAKEMASK1(13)
+#define M_CAUSE_IP5 _MM_MAKEMASK1(12)
+#define M_CAUSE_IP4 _MM_MAKEMASK1(11)
+#define M_CAUSE_IP3 _MM_MAKEMASK1(10)
+#define M_CAUSE_SW2 _MM_MAKEMASK1(9) /* software interrupts */
+#define M_CAUSE_SW1 _MM_MAKEMASK1(8)
+
+#define S_CAUSE_EXC 2
+#define M_CAUSE_EXC _MM_MAKEMASK(5,S_CAUSE_EXC)
+#define V_CAUSE_EXC(x) _MM_MAKEVALUE(x,S_CAUSE_EXC)
+#define G_CAUSE_EXC(x) _MM_GETVALUE(x,S_CAUSE_EXC,M_CAUSE_EXC)
+
+/* Exception Code */
+#define K_CAUSE_EXC_INT 0 /* External interrupt */
+#define K_CAUSE_EXC_MOD 1 /* TLB modification */
+#define K_CAUSE_EXC_TLBL 2 /* TLB miss (Load or Ifetch) */
+#define K_CAUSE_EXC_TLBS 3 /* TLB miss (Save) */
+#define K_CAUSE_EXC_ADEL 4 /* Address error (Load or Ifetch) */
+#define K_CAUSE_EXC_ADES 5 /* Address error (Save) */
+#define K_CAUSE_EXC_IBE 6 /* Bus error (Ifetch) */
+#define K_CAUSE_EXC_DBE 7 /* Bus error (data load or store) */
+#define K_CAUSE_EXC_SYS 8 /* System call */
+#define K_CAUSE_EXC_BP 9 /* Break point */
+#define K_CAUSE_EXC_RI 10 /* Reserved instruction */
+#define K_CAUSE_EXC_CPU 11 /* Coprocessor unusable */
+#define K_CAUSE_EXC_OVF 12 /* Arithmetic overflow */
+#define K_CAUSE_EXC_TRAP 13 /* Trap exception */
+#define K_CAUSE_EXC_VCEI 14 /* Virtual Coherency Exception (I) */
+#define K_CAUSE_EXC_FPE 15 /* Floating Point Exception */
+#define K_CAUSE_EXC_CP2 16 /* Cp2 Exception */
+#define K_CAUSE_EXC_WATCH 23 /* Watchpoint exception */
+#define K_CAUSE_EXC_VCED 31 /* Virtual Coherency Exception (D) */
+
+#define K_NTLBENTRIES 64
+
+#define HI_HALF(x) ((x) >> 16)
+#define LO_HALF(x) ((x) & 0xffff)
+
+/* FPU stuff */
+
+#if defined(__ASSEMBLER__)
+#define C1_CSR $31
+#define C1_FRID $0
+#else
+#define C1_CSR 31
+#define C1_FRID 0
+#endif
+
+#define S_FCSR_CAUSE 12
+#define M_FCSR_CAUSE _MM_MAKEMASK(5,S_FCSR_CAUSE)
+#define V_FCSR_CAUSE(x) _MM_MAKEVALUE(x,S_FCSR_CAUSE)
+#define G_FCSR_CAUSE(x) _MM_GETVALUE(x,S_FCSR_CAUSE,M_FCSR_CAUSE)
+
+#define S_FCSR_ENABLES 7
+#define M_FCSR_ENABLES _MM_MAKEMASK(5,S_FCSR_ENABLES)
+#define V_FCSR_ENABLES(x) _MM_MAKEVALUE(x,S_FCSR_ENABLES)
+#define G_FCSR_ENABLES(x) _MM_GETVALUE(x,S_FCSR_ENABLES,M_FCSR_ENABLES)
+
+#define S_FCSR_FLAGS 2
+#define M_FCSR_FLAGS _MM_MAKEMASK(5,S_FCSR_FLAGS)
+#define V_FCSR_FLAGS(x) _MM_MAKEVALUE(x,S_FCSR_FLAGS)
+#define G_FCSR_FLAGS(x) _MM_GETVALUE(x,S_FCSR_FLAGS,M_FCSR_FLAGS)
+
+
+/*
+ * MIPS64 Config Register (select 0)
+ */
+#define M_CFG_CFG1 _MM_MAKEMASK1(31) /* config1 select1 is impl */
+#define M_CFG_BE _MM_MAKEMASK1(15) /* big-endian mode */
+
+#define S_CFG_AT 13 /* Architecture Type */
+#define M_CFG_AT _MM_MAKEMASK(2,S_CFG_AT)
+#define V_CFG_AT(x) _MM_MAKEVALUE(x,S_CFG_AT)
+#define G_CFG_AT(x) _MM_GETVALUE(x,S_CFG_AT,M_CFG_AT)
+#define K_CFG_AT_MIPS32 0
+#define K_CFG_AT_MIPS64_32 1
+#define K_CFG_AT_MIPS64 2
+
+#define S_CFG_AR 10 /* Architecture Revision */
+#define M_CFG_AR _MM_MAKEMASK(3,S_CFG_AR)
+#define V_CFG_AR(x) _MM_MAKEVALUE(x,S_CFG_AR)
+#define G_CFG_AR(x) _MM_GETVALUE(x,S_CFG_AR,M_CFG_AR)
+#define K_CFG_AR_REV1 0
+
+#define S_CFG_MMU 7 /* MMU Type */
+#define M_CFG_MMU _MM_MAKEMASK(3,S_CFG_MMU)
+#define V_CFG_MMU(x) _MM_MAKEVALUE(x,S_CFG_MMU)
+#define G_CFG_MMU(x) _MM_GETVALUE(x,S_CFG_MMU,M_CFG_MMU)
+#define K_CFG_MMU_NONE 0
+#define K_CFG_MMU_TLB 1
+#define K_CFG_MMU_BAT 2
+#define K_CFG_MMU_FIXED 3
+
+#define S_CFG_K0COH 0 /* K0seg coherency */
+#define M_CFG_K0COH _MM_MAKEMASK(3,S_CFG_K0COH)
+#define V_CFG_K0COH(x) _MM_MAKEVALUE(x,S_CFG_K0COH)
+#define G_CFG_K0COH(x) _MM_GETVALUE(x,S_CFG_K0COH,M_CFG_K0COH)
+#define K_CFG_K0COH_UNCACHED 2
+#define K_CFG_K0COH_CACHEABLE 3
+#define K_CFG_K0COH_COHERENT 5
+
+/*
+ * MIPS64 Config Register (select 1)
+ */
+
+#define M_CFG_CFG2 _MM_MAKEMASK1(31) /* config2 select2 is impl */
+
+#define S_CFG_MMUSIZE 25
+#define M_CFG_MMUSIZE _MM_MAKEMASK(6,S_CFG_MMUSIZE)
+
+#define S_CFG_IS 22
+#define M_CFG_IS _MM_MAKEMASK(3,S_CFG_IS)
+#define V_CFG_IS(x) _MM_MAKEVALUE(x,S_CFG_IS)
+#define G_CFG_IS(x) _MM_GETVALUE(x,S_CFG_IS,M_CFG_IS)
+
+#define S_CFG_IL 19
+#define M_CFG_IL _MM_MAKEMASK(S_CFG_IL,3)
+#define V_CFG_IL(x) _MM_MAKEVALUE(x,S_CFG_IL)
+#define G_CFG_IL(x) _MM_GETVALUE(x,S_CFG_IL,M_CFG_IL)
+
+#define S_CFG_IA 16
+#define M_CFG_IA _MM_MAKEMASK(3,S_CFG_IA)
+#define V_CFG_IA(x) _MM_MAKEVALUE(x,S_CFG_IA)
+#define G_CFG_IA(x) _MM_GETVALUE(x,S_CFG_IA,M_CFG_IA)
+
+#define S_CFG_DS 13
+#define M_CFG_DS _MM_MAKEMASK(3,S_CFG_DS)
+#define V_CFG_DS(x) _MM_MAKEVALUE(x,S_CFG_DS)
+#define G_CFG_DS(x) _MM_GETVALUE(x,S_CFG_DS,M_CFG_DS)
+
+#define S_CFG_DL 10
+#define M_CFG_DL _MM_MAKEMASK(3,S_CFG_DL)
+#define V_CFG_DL(x) _MM_MAKEVALUE(x,S_CFG_DL)
+#define G_CFG_DL(x) _MM_GETVALUE(x,S_CFG_DL,M_CFG_DL)
+
+#define S_CFG_DA 7
+#define M_CFG_DA _MM_MAKEMASK(3,S_CFG_DA)
+#define V_CFG_DA(x) _MM_MAKEVALUE(x,S_CFG_DA)
+#define G_CFG_DA(x) _MM_GETVALUE(x,S_CFG_DA,M_CFG_DA)
+
+#define M_CFG_PC _MM_MAKEMASK1(4) /* perf ctrs present */
+#define M_CFG_WR _MM_MAKEMASK1(3) /* watch regs present */
+#define M_CFG_CA _MM_MAKEMASK1(2) /* MIPS16 present */
+#define M_CFG_EP _MM_MAKEMASK1(1) /* EJTAG present */
+#define M_CFG_FP _MM_MAKEMASK1(0) /* FPU present */
+
+
+
+/*
+ * Primary Cache TagLo
+ */
+
+#define S_TAGLO_PTAG 8
+#define M_TAGLO_PTAG _MM_MAKEMASK(56,S_TAGLO_PTAG)
+
+#define S_TAGLO_PSTATE 6
+#define M_TAGLO_PSTATE _MM_MAKEMASK(2,S_TAGLO_PSTATE)
+#define V_TAGLO_PSTATE(x) _MM_MAKEVALUE(x,S_TAGLO_PSTATE)
+#define G_TAGLO_PSTATE(x) _MM_GETVALUE(x,S_TAGLO_PSTATE,M_TAGLO_PSTATE)
+#define K_TAGLO_PSTATE_INVAL 0
+#define K_TAGLO_PSTATE_SHARED 1
+#define K_TAGLO_PSTATE_CLEAN_EXCL 2
+#define K_TAGLO_PSTATE_DIRTY_EXCL 3
+
+#define M_TAGLO_LOCK _MM_MAKEMASK1(5)
+#define M_TAGLO_PARITY _MM_MAKEMASK1(0)
+
+
+/*
+ * CP0 CacheErr register
+ */
+#define M_CERR_DATA _MM_MAKEMASK1(31) /* err in D space */
+#define M_CERR_SCACHE _MM_MAKEMASK1(30) /* err in l2, not l1 */
+#define M_CERR_DERR _MM_MAKEMASK1(29) /* data error */
+#define M_CERR_TERR _MM_MAKEMASK1(28) /* tag error */
+#define M_CERR_EXTRQ _MM_MAKEMASK1(27) /* external req caused err */
+#define M_CERR_BPAR _MM_MAKEMASK1(26) /* bus parity err */
+#define M_CERR_ADATA _MM_MAKEMASK1(25) /* additional data */
+#define M_CERR_IDX _MM_MAKEMASK(22,0)
+
+
+
+/*
+ * Primary Cache operations
+ */
+#define Index_Invalidate_I 0x0 /* 0 0 */
+#define Index_Writeback_Inv_D 0x1 /* 0 1 */
+#define Index_Invalidate_SI 0x2 /* 0 2 */
+#define Index_Writeback_Inv_SD 0x3 /* 0 3 */
+#define Index_Load_Tag_I 0x4 /* 1 0 */
+#define Index_Load_Tag_D 0x5 /* 1 1 */
+#define Index_Load_Tag_SI 0x6 /* 1 2 */
+#define Index_Load_Tag_SD 0x7 /* 1 3 */
+#define Index_Store_Tag_I 0x8 /* 2 0 */
+#define Index_Store_Tag_D 0x9 /* 2 1 */
+#define Index_Store_Tag_SI 0xA /* 2 2 */
+#define Index_Store_Tag_SD 0xB /* 2 3 */
+#define Create_Dirty_Exc_D 0xD /* 3 1 */
+#define Create_Dirty_Exc_SD 0xF /* 3 3 */
+#define Hit_Invalidate_I 0x10 /* 4 0 */
+#define Hit_Invalidate_D 0x11 /* 4 1 */
+#define Hit_Invalidate_SI 0x12 /* 4 2 */
+#define Hit_Invalidate_SD 0x13 /* 4 3 */
+#define Fill_I 0x14 /* 5 0 */
+#define Hit_Writeback_Inv_D 0x15 /* 5 1 */
+#define Hit_Writeback_Inv_SD 0x17 /* 5 3 */
+#define Hit_Writeback_I 0x18 /* 6 0 */
+#define Hit_Writeback_D 0x19 /* 6 1 */
+#define Hit_Writeback_SD 0x1B /* 6 3 */
+#define Hit_Set_Virtual_SI 0x1E /* 7 2 */
+#define Hit_Set_Virtual_SD 0x1F /* 7 3 */
+
+/* Watchpoint Register */
+#define M_WATCH_PA 0xfffffff8
+#define M_WATCH_R 0x00000002
+#define M_WATCH_W 0x00000001
+
+
+/* TLB entries */
+#define M_TLBHI_ASID _MM_MAKEMASK(0,8)
+#define M_TLBHI_VPN2 _MM_MAKEMASK(27,13)
+
+#define M_TLBLO_G _MM_MAKEMASK1(0)
+#define M_TLBLO_V _MM_MAKEMASK1(1)
+#define M_TLBLO_D _MM_MAKEMASK1(2)
+
+#define S_TLBLO_CALG 3
+#define M_TLBLO_CALG _MM_MAKEMASK(3,S_TLBLO_CALG)
+#define V_TLBLO_CALG(x) _MM_MAKEVALUE(x,S_TLBLO_CALG)
+#define G_TLBLO_CALG(x) _MM_GETVALUE(x,S_TLBLO_CALG,M_TLBLO_CALG)
+
+#define K_CALG_COH_EXCL1_NOL2 0
+#define K_CALG_COH_SHRL1_NOL2 1
+#define K_CALG_UNCACHED 2
+#define K_CALG_NONCOHERENT 3
+#define K_CALG_COH_EXCL 4
+#define K_CALG_COH_SHAREABLE 5
+#define K_CALG_NOTUSED 6
+#define K_CALG_UNCACHED_ACCEL 7
+
+#define S_TLBLO_PFNMASK 6
+#define M_TLBLO_PFNMASK _MM_MAKEMASK(24,S_TLBLO_PFNMASK)
+#define V_TLBLO_PFNMASK(x) _MM_MAKEVALUE(x,S_TLBLO_PFNMASK)
+#define G_TLBLO_PFNMASK(x) _MM_GETVALUE(x,S_TLBLO_PFNMASK,M_TLBLO_PFNMASK)
+
+
+
+#endif /* _SB_MIPS_H */
+
+
diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/include/sbsdram.h b/cfe/cfe/arch/mips/cpu/bcmcore/include/sbsdram.h
new file mode 100644
index 0000000..80e93e3
--- /dev/null
+++ b/cfe/cfe/arch/mips/cpu/bcmcore/include/sbsdram.h
@@ -0,0 +1,92 @@
+/*
+ Copyright 2001, Broadcom Corporation
+ All Rights Reserved.
+
+ This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ the contents of this file may not be disclosed to third parties, copied or
+ duplicated in any form, in whole or in part, without the prior written
+ permission of Broadcom Corporation.
+*/
+/*
+ * BCM47XX Sonics SiliconBackplane SDRAM controller core hardware definitions.
+ *
+ * $Id: sbsdram.h,v 1.1 2001/10/31 18:49:26 mpl Exp $
+ */
+
+#ifndef _SBSDRAM_H
+#define _SBSDRAM_H
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+/* Sonics side: SDRAM core registers */
+typedef volatile struct sbsdramregs {
+ uint32 initcontrol; /* Generates external SDRAM initialization sequence */
+ uint32 config; /* Initializes external SDRAM mode register */
+ uint32 refresh; /* Controls external SDRAM refresh rate */
+ uint32 pad1;
+ uint32 pad2;
+} sbsdramregs_t;
+
+#endif
+
+/* SDRAM initialization control (initcontrol) register bits */
+#define SDRAM_CBR 0x0001 /* Writing 1 generates refresh cycle and toggles bit */
+#define SDRAM_PRE 0x0002 /* Writing 1 generates precharge cycle and toggles bit */
+#define SDRAM_MRS 0x0004 /* Writing 1 generates mode register select cycle and toggles bit */
+#define SDRAM_EN 0x0008 /* When set, enables access to SDRAM */
+#define SDRAM_16Mb 0x0000 /* Use 16 Megabit SDRAM */
+#define SDRAM_64Mb 0x0010 /* Use 64 Megabit SDRAM */
+#define SDRAM_128Mb 0x0020 /* Use 128 Megabit SDRAM */
+#define SDRAM_RSVMb 0x0030 /* Use special SDRAM */
+#define SDRAM_RST 0x0080 /* Writing 1 causes soft reset of controller */
+#define SDRAM_SELFREF 0x0100 /* Writing 1 enables self refresh mode */
+#define SDRAM_PWRDOWN 0x0200 /* Writing 1 causes controller to power down */
+#define SDRAM_32BIT 0x0400 /* When set, indicates 32 bit SDRAM interface */
+#define SDRAM_9BITCOL 0x0800 /* When set, indicates 9 bit column */
+
+/* SDRAM configuration (config) register bits */
+#define SDRAM_BURSTFULL 0x0000 /* Use full page bursts */
+#define SDRAM_BURST8 0x0001 /* Use burst of 8 */
+#define SDRAM_BURST4 0x0002 /* Use burst of 4 */
+#define SDRAM_BURST2 0x0003 /* Use burst of 2 */
+#define SDRAM_CAS3 0x0000 /* Use CAS latency of 3 */
+#define SDRAM_CAS2 0x0004 /* Use CAS latency of 2 */
+
+/* SDRAM refresh control (refresh) register bits */
+#define SDRAM_REF(p) (((p)&0xff) | SDRAM_REF_EN) /* Refresh period */
+#define SDRAM_REF_EN 0x8000 /* Writing 1 enables periodic refresh */
+
+/* SDRAM Core Init values (OCP ID 0x803) */
+
+#define SDRAM_CONFIG SDRAM_BURSTFULL
+#define SDRAM_REFRESH SDRAM_REF(0x40)
+
+#if defined(MEM1MX16_KM)
+#define SDRAM_INIT 0x009
+#elif defined(MEM1MX16X2_KM)
+#define SDRAM_INIT 0x409
+#elif defined(MEM2MX8X2_KM)
+#define SDRAM_INIT 0x809
+#elif defined(MEM2MX8X4_KM)
+#define SDRAM_INIT 0xc09
+#elif defined(MEM2MX32_KM)
+#define SDRAM_INIT 0x439
+#elif defined(MEM4MX16_KM)
+#define SDRAM_INIT 0x019
+#elif defined(MEM4MX16X2_KM)
+#define SDRAM_INIT 0x419
+#elif defined(MEM8MX8X2_KM)
+#define SDRAM_INIT 0x819
+#elif defined(MEM8MX8X4_KM)
+#define SDRAM_INIT 0xc19
+#elif defined(MEM8MX16_KM)
+#define SDRAM_INIT 0x829
+#elif defined(MEM8MX16X2_KM)
+#define SDRAM_INIT 0xc29
+#elif defined(MEM4MX32_KM)
+#define SDRAM_INIT 0x429
+#else /* DEFAULT MEM */
+#define SDRAM_INIT 0x419
+#endif
+
+#endif /* _SBSDRAM_H */
diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/src/Makefile b/cfe/cfe/arch/mips/cpu/bcmcore/src/Makefile
new file mode 100755
index 0000000..76662a0
--- /dev/null
+++ b/cfe/cfe/arch/mips/cpu/bcmcore/src/Makefile
@@ -0,0 +1,8 @@
+
+ALLOBJS += bcmcore_cpuinit.o bcmcore_l1cache.o
+ifeq ($(strip ${CFG_RAMAPP}),1)
+ALLOBJS += bcmcore_arena.o
+endif
+CFLAGS += -mips32 -D_MIPSREGS32_ -mno-abicalls -fPIC
+# CFLAGS += -mips2 -D_MIPSREGS32_
+
diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_arena.c b/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_arena.c
new file mode 100755
index 0000000..b368158
--- /dev/null
+++ b/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_arena.c
@@ -0,0 +1,170 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Physical Memory (arena) manager File: bcmcore_arena.c
+ *
+ * This module describes the physical memory available to the
+ * firmware.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "sbmips.h"
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "lib_arena.h"
+
+#include "cfe_error.h"
+
+#include "cfe.h"
+#include "cfe_mem.h"
+
+#include "initdata.h"
+
+#define _NOPROTOS_
+#include "cfe_boot.h"
+#undef _NOPROTOS_
+
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define ARENA_RANGE(bottom,top,type) arena_markrange(&cfe_arena,(uint64_t)(bottom), \
+ (uint64_t)(top)-(uint64_t)bottom+1,(type),NULL)
+
+#define MEG (1024*1024)
+#define KB 1024
+#define PAGESIZE 4096
+#define CFE_BOOTAREA_SIZE (256*KB)
+#define CFE_BOOTAREA_ADDR 0x20000000
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+extern arena_t cfe_arena;
+
+unsigned int mem_bootarea_start;
+unsigned int mem_bootarea_size;
+
+void bcmcore_arena_init(void);
+void bcmcore_pagetable_init(uint64_t *ptaddr,unsigned int physaddr);
+
+
+/* *********************************************************************
+ * bcmcore_arena_init()
+ *
+ * Create the initial map of physical memory
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void bcmcore_arena_init(void)
+{
+ int64_t memleft;
+
+#if 1 /* defined(CONFIG_MIPS_BRCM) */
+ arena_init(&cfe_arena,0x0,0x0); /* 2^32 physical bytes */
+#else
+ arena_init(&cfe_arena,0x0,0x100000000); /* 2^32 physical bytes */
+#endif
+
+ /*
+ * Mark the ranges from the SB1250's memory map
+ */
+
+ ARENA_RANGE(0x0000000000,0x000FFFFFFF,MEMTYPE_DRAM_NOTINSTALLED);
+
+ /*
+ * Now, fix up the map with what is known about *this* system.
+ *
+ * Do each 256MB chunk.
+ */
+
+ memleft = ((int64_t) mem_totalsize) << 20;
+
+ arena_markrange(&cfe_arena,0x00000000,memleft,MEMTYPE_DRAM_AVAILABLE,NULL);
+
+ /*
+ * Do the boot ROM
+ */
+
+ arena_markrange(&cfe_arena,0x1FC00000,2*1024*1024,MEMTYPE_BOOTROM,NULL);
+
+}
+
+
+/* *********************************************************************
+ * BCMCORE_PAGETABLE_INIT(ptaddr,physaddr)
+ *
+ * This routine constructs the page table. 256KB is mapped
+ * starting at physical address 'physaddr' - the resulting
+ * table entries are placed at 'ptaddr'
+ *
+ * Input parameters:
+ * ptaddr - base of page table
+ * physaddr - starting physical addr of area to map
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void bcmcore_pagetable_init(uint64_t *ptaddr,unsigned int physaddr)
+{
+ int idx;
+
+ for (idx = 0; idx < (CFE_BOOTAREA_SIZE/PAGESIZE); idx++) {
+ ptaddr[idx] = (physaddr >> 6) |
+ V_TLBLO_CALG(K_CALG_NONCOHERENT) |
+ M_TLBLO_V |
+ M_TLBLO_D;
+ physaddr += PAGESIZE;
+ }
+
+}
+
diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_cpuinit.S b/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_cpuinit.S
new file mode 100755
index 0000000..7c04b51
--- /dev/null
+++ b/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_cpuinit.S
@@ -0,0 +1,490 @@
+/* *********************************************************************
+ * SB1250 Board Support Package
+ *
+ * CPU initialization File: bcmcore_cpuinit.S
+ *
+ * This module contains code to initialize the CPU cores.
+ *
+ * Note: all the routines in this module rely on registers only,
+ * since DRAM may not be active yet.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * XX Copyright 2000,2001
+ * Broadcom Corporation. All rights reserved.
+ *
+ * BROADCOM PROPRIETARY AND CONFIDENTIAL
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the license.
+ ********************************************************************* */
+
+#include "sbmips.h"
+#include "exception.h"
+#include "bsp_config.h"
+#include "mipsmacros.h"
+#include "cpu_config.h" /* for ERET and HAZARD */
+
+
+ .text
+
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define LINESIZE 16
+
+#define CACHEOP(cachename,op) ((cachename) | ((op) << 2))
+
+#define CACHE_OP_IDXINVAL 0
+#define CACHE_OP_IDXLOADTAG 1
+#define CACHE_OP_IDXSTORETAG 2
+#define CACHE_OP_IMPLRSVD 3
+#define CACHE_OP_HITINVAL 4
+#define CACHE_OP_FILL 5
+#define CACHE_OP_HITWRITEBACK_INVAL 5
+#define CACHE_OP_HITWRITEBACK 6
+#define CACHE_OP_FETCHLOCK 7
+
+#define L2C 3
+#define L1C_I 0
+#define L1C_D 1
+
+
+/*
+ * Duplicates from cfe_iocb.h -- warning!
+ */
+
+#define CFE_CACHE_FLUSH_D 1
+#define CFE_CACHE_INVAL_I 2
+#define CFE_CACHE_INVAL_D 4
+#define CFE_CACHE_INVAL_L2 8
+#define CFE_CACHE_FLUSH_L2 16
+#define CFE_CACHE_INVAL_RANGE 32
+#define CFE_CACHE_FLUSH_RANGE 64
+
+#define BCMCORE_NTLBENTRIES 32
+
+
+
+#define SENDCHAR(c) \
+ li t0,0xBF800000 ; \
+ li t1,c ; \
+ sb t1,0(t0)
+
+
+#define R_CPU_CP0INIT _TBLIDX(0)
+#define R_CPU_L1CINIT _TBLIDX(1)
+#define R_CPU_SETLEDS _TBLIDX(2)
+#define R_CPU_L1CFLASHD _TBLIDX(3)
+#define R_CPU_L1CINVALI _TBLIDX(4)
+
+#define SETLEDS1(a,b,c,d) \
+ li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \
+ CALLINIT_KSEG1(cpuinit_table,R_CPU_SETLEDS)
+#define SETLEDS(a,b,c,d) \
+ li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \
+ CALLINIT_KSEG0(cpuinit_table,R_CPU_SETLEDS)
+
+cpuinit_table:
+ _LONG_ bcmcore_cp0_init # [ 0 ] R_CPU_CP0INIT
+ _LONG_ bcmcore_l1cache_init # [ 1 ] R_CPU_L1CINIT
+ _LONG_ board_setleds # [ 2 ] R_CPU_SETLEDS
+ _LONG_ bcmcore_l1cache_flush_d # [ 3 ] R_CPU_L1CFLASHD
+ _LONG_ bcmcore_l1cache_inval_i # [ 4 ] R_CPU_L1CINVALI
+
+
+/* *********************************************************************
+ * BCMCORE_CP0_INIT()
+ *
+ * Initialize an BCMCORE CPU's CP0 registers
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * all
+ ********************************************************************* */
+
+
+LEAF(bcmcore_cp0_init)
+
+ .set noreorder
+
+ mtc0 zero,C0_WATCHLO # Watch registers.
+ mtc0 zero,C0_WATCHHI
+ mtc0 zero,C0_CAUSE # must clear before writing SR
+
+ mfc0 v0,C0_SR # Get status register
+ and v0,M_SR_SR # preserve soft reset
+#ifdef DEBUG_ENV_ICE
+ and v0,~M_SR_BEV
+#else
+ or v0,M_SR_BEV # exceptions to boot vector
+#endif
+ mtc0 v0,C0_SR # set up the status register
+
+
+ mfc0 v0,C0_CONFIG # get current CONFIG register
+ srl v0,v0,3 # strip out K0 bits
+ sll v0,v0,3 # k0 bits now zero
+ or v0,v0,K_CFG_K0COH_CACHEABLE # K0 is cacheable.
+ mtc0 v0,C0_CONFIG
+ nop
+
+ mtc0 zero,C0_WATCHLO # Watch registers.
+ mtc0 zero,C0_WATCHHI
+
+ mtc0 zero,C0_TLBHI # TLB entry (high half)
+ nop
+
+
+ #
+ # This is probably not the right init value for C0_COMPARE,
+ # but it seems to be necessary for the sim model right now.
+ #
+
+ li v0,-1
+ mtc0 v0,C0_COMPARE
+ nop
+
+ #
+ # Initialize all the TLB entries to some invalid value
+ #
+
+ mtc0 zero,C0_TLBLO0 /* tlblo0 = invalid */
+ nop
+ mtc0 zero,C0_TLBLO1 /* tlblo1 = invalid */
+ nop
+ mtc0 zero,C0_PGMASK /* 4K pages */
+ nop
+
+ li t0,K1BASE /* tlbhi = impossible vpn */
+ li t1,(BCMCORE_NTLBENTRIES-1) /* index */
+
+
+ nop
+1: mtc0 t0,C0_TLBHI
+ nop
+ mtc0 t1,C0_INX
+ nop
+ addu t0,0x2000 /* inc vpn */
+ tlbwi
+ bnez t1,1b
+ subu t1,1 # BDSLOT
+ .set reorder
+
+
+/*
+ * XXX What other CP0 initialization do I need?
+ */
+
+ jr ra
+
+
+END(bcmcore_cp0_init)
+
+
+/* *********************************************************************
+ * BCMCORE_CPUINIT
+ *
+ * Do initialization of the Broadcom core
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+LEAF(bcmcore_cpuinit)
+
+ move fp,ra
+
+ SETLEDS1('C','P','U','I')
+ CALLINIT_KSEG1(cpuinit_table,R_CPU_CP0INIT)
+
+ SETLEDS1('L','1','C','I')
+ CALLINIT_KSEG1(cpuinit_table,R_CPU_L1CINIT)
+
+ move ra,fp
+ j ra
+
+END(bcmcore_cpuinit)
+
+
+/* *********************************************************************
+ * BCMCORE_KSEG0_SWITCH
+ *
+ * Return to the address of the routine that called us, except
+ * in K0seg instead of K1seg
+ *
+ * Input parameters:
+ * nothing - ra is return address
+ *
+ * Return value:
+ * ra = same return address in K0
+ ********************************************************************* */
+
+LEAF(bcmcore_kseg0_switch)
+
+ and ra,(K0SIZE-1)
+ or ra,K0BASE
+ jr ra
+
+END(bcmcore_kseg0_switch)
+
+/* *********************************************************************
+ * BCMCORE_NULL
+ *
+ * Dummy handler for routines we don't need to implement, like
+ * the multiprocessor stuff
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * none
+ ********************************************************************* */
+
+LEAF(bcmcore_null)
+
+ j ra
+
+END(bcmcore_null)
+
+
+/* *********************************************************************
+ * BCMCORE_CPURESTART
+ *
+ * This routine is called when someone soft-exits to CFE. We
+ * reinitialize any CP0 stuff here.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(bcmcore_cpurestart)
+
+ j ra
+
+END(bcmcore_cpurestart)
+
+
+/* *********************************************************************
+ * BCMCORE_CACHEOPS
+ *
+ * Perform various cache operations on a BCM Core
+ *
+ * Input parameters:
+ * a0 - flag bits (CFE_CACHE_xxx)
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * t0,t1,t2,t3,v1,s0
+ ********************************************************************* */
+
+LEAF(bcmcore_cacheops)
+
+ move s0,ra
+
+ move v1,a0
+
+ /*
+ * With no flags, we flush L1D and invalid L1I
+ */
+
+ bne v1,zero,1f
+ li v1,CFE_CACHE_FLUSH_D | CFE_CACHE_INVAL_I
+1:
+
+ /*
+ * Flush the D-Cache, since the program we loaded is "data".
+ */
+
+ and a0,v1,CFE_CACHE_FLUSH_D
+ beq a0,zero,1f
+ CALLINIT_KSEG1(cpuinit_table,R_CPU_L1CFLASHD)
+1:
+
+ /*
+ * Invalidate the I-Cache, so that addresses in the program
+ * region will miss and need to be filled from the data we
+ * just flushed above.
+ */
+
+ and a0,v1,CFE_CACHE_INVAL_I
+ beq a0,zero,1f
+ CALLINIT_KSEG1(cpuinit_table,R_CPU_L1CINVALI)
+1:
+
+
+ .set push
+ .set mips32
+
+ /*
+ * Invalidate cache range
+ */
+
+ and a0,v1,CFE_CACHE_INVAL_RANGE
+ beq a0,zero,2f
+
+ move t0,a1
+1: cache CACHEOP(L1C_D,CACHE_OP_HITINVAL),0(t0)
+ add t0,LINESIZE
+ blt t0,a2,1b
+
+ /*
+ * Flush cache range
+ */
+
+
+2:
+ and a0,v1,CFE_CACHE_FLUSH_RANGE
+ beq a0,zero,2f
+
+ move t0,a1
+1: cache CACHEOP(L1C_D,CACHE_OP_HITWRITEBACK_INVAL),0(t0)
+ add t0,LINESIZE
+ blt t0,a2,1b
+
+2:
+
+ .set pop
+
+
+ move ra,s0
+ j ra
+
+END(bcmcore_cacheops)
+
+
+
+/* *********************************************************************
+ * BCMCORE_TLBHANDLER
+ *
+ * This is the TLB exception handler for the bcmcore
+ *
+ * Note: only K0 and K1 are available to us at this time.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+LEAF(bcmcore_tlbhandler)
+ .set noreorder
+ .set noat
+
+/*
+ * XXX XXX XXX XXX XXX
+ *
+ * This won't work as-is on the BCMCORE. The CONTEXT register is not
+ * wide enough! In fact, it's broken on all pre-mips4 CPUs.
+ *
+ * XXX XXX XXX XXX XXX
+ */
+
+/*
+ * This requires a bit of explanation: We only support 256KB
+ * of mapped space for the boot program. This space will be
+ * mapped from 0x2000_0000 to 0x2004_0000 to some physical
+ * memory allocated by the firmware. This is 64 pages
+ * of 4KB each.
+ *
+ * We know our BadVPN2 will be in the range
+ * 0x100000 to 0x1001F0, since the memory is mapped from
+ * 0x2000_0000 to 0x2004_0000. BadVPN2 plus the four bits
+ * of zeroes at the end are bits 31..9
+ *
+ * We also want to place the PTEbase on something other than
+ * a 16MB boundary. Each entry is 16 bytes, and there
+ * are 64 entries, so we need only 10 bits to address
+ * the entire table (it can therefore be aligned on a
+ * 1KB boundary).
+ *
+ * To make this work, we'll shift PTEbase to the right, leaving
+ * the bottom ten bits for the page number, as:
+ *
+ * Bits 31..10: PTEbase
+ * Bits 9..4: BadVPN
+ * Bits 3..0: 16 bytes for table entry
+ *
+ * Therefore:
+ * PTEbase gets shifted right 13 bits.
+ * BadVPN gets masked at 6 bits (mask is 0x3F0)
+ * The bottom 4 bits are zero.
+ *
+ * To range check the address, we can shift the Bad VPN
+ * right by 9 bits, and check for values of 0x1000 and
+ * 0x1001.
+ */
+
+
+ /*
+ * This part range checks the VPN2 field in the
+ * context register. We only handle
+ * VPN2s in the range 0x100000 to 0x1001F0
+ */
+ mfc0 k0,C0_TLBHI
+
+ mfc0 k0,C0_CTEXT # Get context
+ sra k0,8 # keep hi part
+ and k0,0x1FFF # of VPN2
+ li k1,0x1000 # 0x1000 is ok
+ beq k0,k1,1f #
+ nop # BDSLOT
+ li k1,0x1001 # 0x1001 is ok
+ beq k0,k1,1f #
+ nop # BDSLOT
+
+ li k0,XTYPE_TLBFILL # all other bits are not
+ b _exc_entry
+ nop # BDSLOT
+
+1: mfc0 k0,C0_CTEXT # Get context
+ sra k0,13 # Shift PTEbase
+ li k1,0x3FF # Generate mask to kill
+ not k1 # BadVPN2 bits
+ and k0,k1 # keep only PTEBase part.
+
+ mfc0 k1,C0_CTEXT # Get Context
+ and k1,0x3F0 # Keep only BadVPN2 bits
+ or k1,k0 # Replace PTEBase
+
+ ld k0,0(k1) # Load entrylo0
+ ld k1,8(k1) # Load entrylo1
+ mtc0 k0,C0_TLBLO0 # and write to CP0
+ mtc0 k1,C0_TLBLO1
+ tlbwr # put it in the TLB
+ ERET
+ nop
+
+ .set reorder
+ .set at
+
+END(bcmcore_tlbhandler)
+
+
+/* *********************************************************************
+ * End
+ ********************************************************************* */
+
diff --git a/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_l1cache.S b/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_l1cache.S
new file mode 100755
index 0000000..fa39bfd
--- /dev/null
+++ b/cfe/cfe/arch/mips/cpu/bcmcore/src/bcmcore_l1cache.S
@@ -0,0 +1,219 @@
+/* *********************************************************************
+ * SB1250 Board Support Package
+ *
+ * L1C initialization File: bcmcore_l1cache.S
+ *
+ * This module contains code to initialize the CPU's caches
+ *
+ * Note: all the routines in this module rely on registers only,
+ * since DRAM may not be active yet.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * XX Copyright 2000,2001
+ * Broadcom Corporation. All rights reserved.
+ *
+ * BROADCOM PROPRIETARY AND CONFIDENTIAL
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the license.
+ ********************************************************************* */
+
+#include "sbmips.h"
+#include "bsp_config.h"
+
+ .text
+
+ .set push
+ .set mips32
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define CP0_CFG_ISMSK (0x7 << 22)
+#define CP0_CFG_ISSHF 22
+#define CP0_CFG_ILMSK (0x7 << 19)
+#define CP0_CFG_ILSHF 19
+#define CP0_CFG_IAMSK (0x7 << 16)
+#define CP0_CFG_IASHF 16
+#define CP0_CFG_DSMSK (0x7 << 13)
+#define CP0_CFG_DSSHF 13
+#define CP0_CFG_DLMSK (0x7 << 10)
+#define CP0_CFG_DLSHF 10
+#define CP0_CFG_DAMSK (0x7 << 7)
+#define CP0_CFG_DASHF 7
+
+#define cacheop(kva, size, linesize, op) \
+ .set noreorder; \
+ addu t1, kva, size; \
+ subu t2, linesize, 1; \
+ not t2; \
+ and t0, kva, t2; \
+ addu t1, -1; \
+ and t1, t2; \
+10: cache op, 0(t0); \
+ bne t0, t1, 10b; \
+ addu t0, linesize; \
+11: \
+ .set reorder
+
+#define size_icache(size, linesize) \
+ mfc0 t7, C0_CONFIG, 1; \
+ and t0, t7, CP0_CFG_ILMSK; \
+ srl t0, t0, CP0_CFG_ILSHF; \
+ move linesize, zero; \
+ beq t0, zero,1f; \
+ add t0, 1; \
+ li linesize, 1; \
+ sll linesize, t0; \
+1: and t0, t7, CP0_CFG_ISMSK; \
+ srl t0, t0, CP0_CFG_ISSHF; \
+ li size, 64; \
+ sll size, t0; \
+ and t0, t7, CP0_CFG_IAMSK; \
+ srl t0, t0, CP0_CFG_IASHF; \
+ add t0, 1; \
+ mult size, t0; \
+ mflo size; \
+ mult size, linesize; \
+ mflo size
+
+#define size_dcache(size, linesize) \
+ mfc0 t7, C0_CONFIG, 1; \
+ and t0, t7, CP0_CFG_DLMSK; \
+ srl t0, t0, CP0_CFG_DLSHF; \
+ move linesize, zero; \
+ beq t0, zero,1f; \
+ add t0, 1; \
+ li linesize, 1; \
+ sll linesize, t0; \
+1: and t0, t7, CP0_CFG_DSMSK; \
+ srl t0, t0, CP0_CFG_DSSHF; \
+ li size, 64; \
+ sll size, t0; \
+ and t0, t7, CP0_CFG_DAMSK; \
+ srl t0, t0, CP0_CFG_DASHF; \
+ add t0, 1; \
+ mult size, t0; \
+ mflo size; \
+ mult size, linesize; \
+ mflo size
+
+
+/* *********************************************************************
+ * BCMCORE_L1CACHE_INIT()
+ *
+ * Initialize the L1 Cache
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * t0,t1,t2
+ ********************************************************************* */
+
+LEAF(bcmcore_l1cache_init)
+
+ mtc0 zero, C0_TAGLO # Initialize TAGLO register
+ mtc0 zero, C0_TAGLO,1 # Initialize DataLo register
+
+ li a0, K0BASE # Initialise primary instruction cache.
+ size_icache(a1, a2)
+ cacheop(a0, a1, a2, Index_Store_Tag_I)
+
+ li a0, K0BASE # Initialise primary data cache.
+ size_dcache(a1, a2)
+ cacheop(a0, a1, a2, Index_Store_Tag_D)
+
+ jr ra
+
+END(bcmcore_l1cache_init)
+
+/* *********************************************************************
+ * BCMCORE_L1CACHE_INVAL_I()
+ *
+ * Invalidate the entire ICache
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * t0,t1,t2
+ ********************************************************************* */
+LEAF(bcmcore_l1cache_inval_i)
+
+ li a0, K0BASE
+ size_icache(a1, a2)
+ cacheop(a0, a1, a2, Index_Invalidate_I)
+
+ j ra
+
+END(bcmcore_l1cache_inval_i)
+
+/* *********************************************************************
+ * BCMCORE_L1CACHE_FLUSH_D()
+ *
+ * Flush the entire DCache
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * t0,t1,t2
+ ********************************************************************* */
+LEAF(bcmcore_l1cache_flush_d)
+
+ li a0, K0BASE
+ size_dcache(a1, a2)
+
+# before flushing cache clear tags pointing to flash memory to avoid writes into flash
+ addu t1, a0, a1
+ subu t2, a2, 1
+ not t2
+ and t0, a0, t2
+ addu t1, -1
+ and t1, t2
+1:
+ cache Index_Load_Tag_D, 0(t0)
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ mfc0 t2, C0_TAGLO # Read TAGLO register
+ and t2, 0x1f000000 # check address
+ li t3, 0x1f000000
+ bne t2, t3, 2f
+ mtc0 zero, C0_TAGLO
+ cache Index_Store_Tag_D, 0(t0) # Reset tag for flash memory locations
+2:
+ .set noreorder;
+ bne t0, t1, 1b
+ addu t0, a2
+ .set reorder
+
+ cacheop(a0, a1, a2, Index_Writeback_Inv_D)
+
+ j ra
+
+END(bcmcore_l1cache_flush_d)
+
+ .set pop
+
+/* *********************************************************************
+ * End
+ ********************************************************************* */
+
diff --git a/cfe/cfe/dev/SIBYTE_PRIVATE_FILES b/cfe/cfe/dev/SIBYTE_PRIVATE_FILES
new file mode 100644
index 0000000..eae0411
--- /dev/null
+++ b/cfe/cfe/dev/SIBYTE_PRIVATE_FILES
@@ -0,0 +1,6 @@
+dev_ptflash.c
+bcm5700.h
+dev_bcm5700.c
+bcm5821.h
+dev_bcm5821.c
+
diff --git a/cfe/cfe/dev/bcm5700.h b/cfe/cfe/dev/bcm5700.h
new file mode 100644
index 0000000..76aa3ea
--- /dev/null
+++ b/cfe/cfe/dev/bcm5700.h
@@ -0,0 +1,1007 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * BCM5700 (10/100/1K EthernetMAC) registers File: bcm5700.c
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifndef _BCM5700_H_
+#define _BCM5700_H_
+
+/*
+ * Register and bit definitions for the Broadcom BCM570X family (aka
+ * Tigon3) of Integrated MACs.
+ *
+ * References:
+ *
+ * Host Programmer Interface Specification for the BCM570X Family
+ * of Highly-Integrated Media Access Controllers, 570X-PG106-R.
+ * Broadcom Corp., 16215 Alton Parkway, Irvine CA, 09/27/02
+ *
+ * Simplified Programmer Interface Specification for the BCM570X Family
+ * of Highly Integrated Media Access Controllers, 570X-PG202-R.
+ * Broadcom Corp., 16215 Alton Parkway, Irvine CA, 10/14/02
+ */
+
+#define K_PCI_VENDOR_BROADCOM 0x14e4
+#define K_PCI_ID_BCM5700 0x1644
+#define K_PCI_ID_BCM5701 0x1645
+#define K_PCI_ID_BCM5702 0x16A6
+#define K_PCI_ID_BCM5703 0x16A7
+#define K_PCI_ID_BCM5704C 0x1648
+#define K_PCI_ID_BCM5704S 0x16A8
+#define K_PCI_ID_BCM5705 0x1653
+
+#define _DD_MAKEMASK1(n) (1 << (n))
+#define _DD_MAKEMASK(v,n) ((((1)<<(v))-1) << (n))
+#define _DD_MAKEVALUE(v,n) ((v) << (n))
+#define _DD_GETVALUE(v,n,m) (((v) & (m)) >> (n))
+
+
+/* Registers 0x0000 - 0x00FF are PCI Configuration registers (shadow) */
+
+#define PCI_PCIX_CMD_REG 0x40
+#define PCI_PCIX_STAT_REG 0x44
+
+#define PCI_PMC_REG 0x48
+#define PCI_PMCSR_REG 0x4C
+
+#define R_MISC_HOST_CTRL 0x0068
+#define R_DMA_RW_CTRL 0x006C
+#define R_PCI_STATE 0x0070
+#define R_PCI_CLK_CTRL 0x0074
+#define R_REG_BASE_ADDR 0x0078
+#define R_MEMWIN_BASE_ADDR 0x007C
+#define R_REG_DATA 0x0080
+#define R_MEMWIN_DATA 0x0084
+/* For 5700 and 5701, 0x0088-0x0090 shadow 0x6800-0x6808 */
+#define R_INT_MBOX0 0x0B0 /* 8 bytes, shadows R_INT_MBOX(0) */
+
+/* Registers 0x0200 - 0x03FF are High Priority Mailbox registers */
+
+#define R_INT_MBOX(n) (0x0200 + 8*(n)) /* 0 <= n < 4 */
+#define R_GEN_MBOX(n) (0x0220 + 8*(n)-8) /* 1 <= n <= 8 */
+#define R_RELOAD_STATS_MBOX 0x0260
+#define R_RCV_BD_STD_PI 0x0268
+#define R_RCV_BD_JUMBO_PI 0x0270
+#define R_RCV_BD_MINI_PI 0x0278
+#define R_RCV_BD_RTN_CI(n) (0x0280 + 8*(n)-8) /* 1 <= n <= 16 */
+#define R_SND_BD_PI(n) (0x0300 + 8*(n)-8) /* 1 <= n <= 16 */
+#define R_SND_BD_NIC_PI(n) (0x0380 + 8*(n)-8) /* 1 <= n <= 16 */
+
+/* Registers 0x0400 - 0x0BFF are MAC Control registers */
+
+#define R_MAC_MODE 0x0400
+#define R_MAC_STATUS 0x0404
+#define R_MAC_EVENT_ENB 0x0408
+#define R_MAC_LED_CTRL 0x040C
+
+#define R_MAC_ADDR1_HIGH 0x0410
+#define R_MAC_ADDR1_LOW 0x0414
+#define R_MAC_ADDR2_HIGH 0x0418
+#define R_MAC_ADDR2_LOW 0x041C
+#define R_MAC_ADDR3_HIGH 0x0420
+#define R_MAC_ADDR3_LOW 0x0424
+#define R_MAC_ADDR4_HIGH 0x0428
+#define R_MAC_ADDR4_LOW 0x042C
+
+#define R_WOL_PATTERN_PTR 0x0430
+#define R_WOL_PATTERN_CFG 0x0434
+#define R_TX_BACKOFF 0x0438
+#define R_RX_MTU 0x043C
+#define R_PCS_TEST 0x0440
+#define R_TX_AUTONEG 0x0444
+#define R_RX_AUTONEG 0x0448
+
+#define R_MI_COMM 0x044C
+#define R_MI_STATUS 0x0450
+#define R_MI_MODE 0x0454
+
+#define R_AUTOPOLL_STAT 0x0458
+#define R_TX_MODE 0x045C
+#define R_TX_STAT 0x0460
+#define R_TX_LENS 0x0464
+#define R_RX_MODE 0x0468
+#define R_RX_STAT 0x046C
+
+#define R_MAC_HASH(n) (0x0470 + 4*(n)) /* 0 <= n < 4 */
+
+#define R_RX_BD_RULES_CTRL(n) (0x0480 + 8*(n)) /* 0 <= n < 16 */
+#define R_RX_BD_RULES_MASK(n) (0x0484 + 8*(n))
+
+#define R_RX_RULES_CFG 0x0500
+#define R_RX_FRAMES_LOW 0x0504
+#define R_MAC_HASH_EXT(n) (0x0520 + 4*(n)) /* 0 <= n < 4 */
+#define R_MAC_ADDR_EXT(n) (0x0530 + 8*(n)) /* 0 <= n < 12 */
+#define R_SERDES_CTRL 0x0590
+#define R_SERDES_STAT 0x0594
+#define R_RX_STATS_MEM 0x0800
+#define R_TX_STATS_MEM 0x0880
+
+
+/*
+ * Note on Buffer Descriptor (BD) Ring indices:
+ * Numbering follows Broadcom literature, which uses indices 1-16.
+ * PI = producer index, CI = consumer index.
+ */
+
+/* Registers 0x0C00 - 0x0FFF are Send Data Initiator Control registers */
+
+#define R_SND_DATA_MODE 0x0C00
+#define R_SND_DATA_STAT 0x0C04
+#define R_SND_DATA_STATS_CTRL 0x0C08
+#define R_SND_DATA_STATS_ENB 0x0C0C
+#define R_SND_DATA_STATS_INCR 0x0C10
+
+#define R_STATS_CTR_SND_COS(n) (0x0C80 + 4*(n)-4) /* 1 <= n <= 16 */
+#define R_STATS_DMA_RDQ_FULL 0x0CC0
+#define R_STATS_DMA_HP_RDQ_FULL 0x0CC4
+#define R_STATS_SDCQ_FULL 0x0CC8
+#define R_STATS_NIC_SET_SND_PI 0x0CCC
+#define R_STATS_STAT_UPDATED 0x0CD0
+#define R_STATS_IRQS 0x0CD4
+#define R_STATS_IRQS_AVOIDED 0x0CD8
+#define R_STATS_SND_THRSH_HIT 0x0CDC
+
+/* Registers 0x1000 - 0x13FF are Send Data Completion Control registers */
+
+#define R_SND_DATA_COMP_MODE 0x1000
+
+/* Registers 0x1400 - 0x17FF are Send BD Ring Selection Control registers */
+
+#define R_SND_BD_SEL_MODE 0x1400
+#define R_SND_BD_SEL_STAT 0x1404
+#define R_SND_BD_DIAG 0x1408
+#define R_SND_BD_SEL_CI(n) (0x1440 + 4*(n)-4) /* 1 <= n <= 16 */
+
+/* Registers 0x1800 - 0x1BFF are Send BD Initiator Control registers */
+
+#define R_SND_BD_INIT_MODE 0x1800
+#define R_SND_BD_INIT_STAT 0x1804
+#define R_SND_BD_INIT_PI(n) (0x1808 + 4*(n)-4) /* 1 <= n <= 16 */
+
+/* Registers 0x1C00 - 0x1FFF are Send BD Completion Control registers */
+
+#define R_SND_BD_COMP_MODE 0x1C00
+
+/* Registers 0x2000 - 0x23FF are Receive List Placement Control registers */
+
+#define R_RCV_LIST_MODE 0x2000
+#define R_RCV_LIST_STAT 0x2004
+#define R_RCV_LIST_LOCK 0x2008
+#define R_RCV_NONEMPTY_BITS 0x200C
+#define R_RCV_LIST_CFG 0x2010
+#define R_RCV_LIST_STATS_CTRL 0x2014
+#define R_RCV_LIST_STATS_ENB 0x2018
+#define R_RCV_LIST_STATS_INC 0x201C
+#define R_RCV_LIST_HEAD(n) (0x2100 + 16*(n)-16) /* 1 <= n <= 16 */
+#define R_RCV_LIST_TAIL(n) (0x2104 + 16*(n)-16)
+#define R_RCV_LIST_CNT(n) (0x2108 + 16*(n)-16)
+#define R_STATS_CTR_RCV_COS(n) (0x2200 + 4*(n)-4) /* 1 <= n <= 16 */
+#define R_STATS_FILT_DROP 0x2240
+#define R_STATS_DMA_WRQ_FULL 0x2244
+#define R_STATS_DMA_HP_WRQ_FULL 0x2248
+#define R_STATS_NO_RCV_BDS 0x224C
+#define R_STATS_IN_DISCARDS 0x2250
+#define R_STATS_IN_ERRORS 0x2254
+#define R_STATS_RCV_THRSH_HIT 0x2258
+
+/* Registers 0x2400 - 0x27FF are Receive Data/BD Initiator Control registers */
+
+#define R_RCV_DATA_INIT_MODE 0x2400
+#define R_RCV_DATA_INIT_STAT 0x2404
+#define R_JUMBO_RCV_BD_RCB 0x2440 /* 16 bytes */
+#define R_STD_RCV_BD_RCB 0x2450 /* 16 bytes */
+#define R_MINI_RCV_BD_RCB 0x2460 /* 16 bytes */
+#define R_RCV_BD_INIT_JUMBO_CI 0x2470
+#define R_RCV_BD_INIT_STD_CI 0x2474
+#define R_RCV_BD_INIT_MINI_CI 0x2478
+#define R_RCV_BD_INIT_RTN_PI(n) (0x2480 + 4*(n)-4) /* 1 <= n <= 16 */
+#define R_RCV_BD_INIT_DIAG 0x24C0
+
+/* Registers 0x2800 - 0x2BFF are Receive Data Completion Control registers */
+
+#define R_RCV_COMP_MODE 0x2800
+
+/* Registers 0x2C00 - 0x2FFF are Receive BD Initiator Control registers */
+
+#define R_RCV_BD_INIT_MODE 0x2C00
+#define R_RCV_BD_INIT_STAT 0x2C04
+#define R_RCV_BD_INIT_JUMBO_PI 0x2C08
+#define R_RCV_BD_INIT_STD_PI 0x2C0C
+#define R_RCV_BD_INIT_MINI_PI 0x2C10
+#define R_MINI_RCV_BD_THRESH 0x2C14
+#define R_STD_RCV_BD_THRESH 0x2C18
+#define R_JUMBO_RCV_BD_THRESH 0x2C1C
+
+/* Registers 0x3000 - 0x33FF are Receive BD Completion Control registers */
+
+#define R_RCV_BD_COMP_MODE 0x3000
+#define R_RCV_BD_COMP_STAT 0x3004
+#define R_NIC_JUMBO_RCV_BD_PI 0x3008
+#define R_NIC_STD_RCV_BD_PI 0x300C
+#define R_NIC_MINI_RCV_BD_PI 0x3010
+
+/* Registers 0x3400 - 0x37FF are Receive List Selector Control registers */
+
+#define R_RCV_LIST_SEL_MODE 0x3400
+#define R_RCV_LIST_SEL_STATUS 0x3404
+
+/* Registers 0x3800 - 0x3BFF are Mbuf Cluster Free registers */
+
+#define R_MBUF_FREE_MODE 0x3800
+#define R_MBUF_FREE_STATUS 0x3804
+
+/* Registers 0x3C00 - 0x3FFF are Host Coalescing Control registers */
+
+#define R_HOST_COAL_MODE 0x3C00
+#define R_HOST_COAL_STAT 0x3C04
+#define R_RCV_COAL_TICKS 0x3C08
+#define R_SND_COAL_TICKS 0x3C0C
+#define R_RCV_COAL_MAX_CNT 0x3C10
+#define R_SND_COAL_MAX_CNT 0x3C14
+#define R_RCV_COAL_INT_TICKS 0x3C18
+#define R_SND_COAL_INT_TICKS 0x3C1C
+#define R_RCV_COAL_INT_CNT 0x3C20
+#define R_SND_COAL_INT_CNT 0x3C24
+#define R_STATS_TICKS 0x3C28
+#define R_STATS_HOST_ADDR 0x3C30 /* 8 bytes */
+#define R_STATUS_HOST_ADDR 0x3C38 /* 8 bytes */
+#define R_STATS_BASE_ADDR 0x3C40
+#define R_STATUS_BASE_ADDR 0x3C44
+#define R_FLOW_ATTN 0x3C48
+#define R_NIC_JUMBO_RCV_BD_CI 0x3C50
+#define R_NIC_STD_RCV_BD_CI 0x3C54
+#define R_NIC_MINI_RCV_BD_CI 0x3C58
+#define R_NIC_RTN_PI(n) (0x3C80 + 4*(n)-4) /* 1 <= n <= 16 */
+#define R_NIC_SND_BD_CD(n) (0x3CC0 + 4*(n)-4) /* 1 <= n <= 16 */
+
+/* Registers 0x4000 - 0x43FF are Memory Arbiter registers */
+
+#define R_MEM_MODE 0x4000
+#define R_MEM_STATUS 0x4004
+#define R_MEM_TRAP_LOW 0x4008
+#define R_MEM_TRAP_HIGH 0x400C
+
+
+/* Registers 0x4400 - 0x47FF are Buffer Manager Control registers */
+
+#define R_BMGR_MODE 0x4400
+#define R_BMGR_STATUS 0x4404
+#define R_BMGR_MBUF_BASE 0x4408
+#define R_BMGR_MBUF_LEN 0x440C
+#define R_BMGR_MBUF_DMA_LOW 0x4410
+#define R_BMGR_MBUF_RX_LOW 0x4414
+#define R_BMGR_MBUF_HIGH 0x4418
+
+#define R_BMGR_DMA_BASE 0x442C
+#define R_BMGR_DMA_LEN 0x4430
+#define R_BMGR_DMA_LOW 0x4434
+#define R_BMGR_DMA_HIGH 0x4438
+
+#define R_BMGR_DIAG1 0x444C
+#define R_BMGR_DIAG2 0x4450
+#define R_BMGR_DIAG3 0x4454
+#define R_BMGR_RCV_FLOW_THRESH 0x4458
+
+/* Registers 0x4800 - 0x4BFF are Read DMA Control registers */
+
+#define R_RD_DMA_MODE 0x4800
+#define R_RD_DMA_STAT 0x4804
+
+/* Registers 0x4C00 - 0x4FFF are Write DMA Control registers */
+
+#define R_WR_DMA_MODE 0x4C00
+#define R_WR_DMA_STAT 0x4C04
+
+/* Registers 0x5000 - 0x53FF are RX RISC registers */
+
+#define R_RX_RISC_MODE 0x5000
+#define R_RX_RISC_STATE 0x5004
+#define R_RX_RISC_PC 0x501C
+
+/* Registers 0x5400 - 0x57FF are TX RISC registers */
+
+#define R_TX_RISC_MODE 0x5400
+#define R_TX_RISC_STATE 0x5404
+#define R_TX_RISC_PC 0x541C
+
+/* Registers 0x5800 - 0x5BFF are Low Priority Mailbox registers (8 bytes) */
+
+#define R_LP_INT_MBOX(n) (0x5800 + 8*(n)) /* 0 <= n < 4 */
+#define R_LP_GEN_MBOX(n) (0x5820 + 8*(n)-8) /* 1 <= n <= 8 */
+#define R_LP_RELOAD_STATS_MBOX 0x5860
+#define R_LP_RCV_BD_STD_PI 0x5868
+#define R_LP_RCV_BD_JUMBO_PI 0x5870
+#define R_LP_RCV_BD_MINI_PI 0x5878
+#define R_LP_RCV_BD_RTN_CI(n) (0x5880 + 8*(n)-8) /* 1 <= n <= 16 */
+#define R_LP_SND_BD_PI(n) (0x5900 + 8*(n)-8) /* 1 <= n <= 16 */
+
+/* Registers 0x5C00 - 0x5C03 are Flow Through Queues */
+
+#define R_FTQ_RESET 0x5C00
+
+/* Registers 0x6000 - 0x63FF are Message Signaled Interrupt registers */
+
+/* Registers 0x6400 - 0x67FF are DMA Completion registers */
+
+#define R_DMA_COMP_MODE 0x6400
+
+/* Registers 0x6800 - 0x68ff are General Control registers */
+
+#define R_MODE_CTRL 0x6800
+#define R_MISC_CFG 0x6804
+#define R_MISC_LOCAL_CTRL 0x6808
+#define R_TIMER 0x680C
+#define R_MEM_PWRUP 0x6030 /* 8 bytes */
+#define R_EEPROM_ADDR 0x6838
+#define R_EEPROM_DATA 0x683C
+#define R_EEPROM_CTRL 0x6840
+#define R_MDI_CTRL 0x6844
+#define R_EEPROM_DELAY 0x6848
+
+/* Registers 0x6C00 - 0x6CFF are ASF Support registers (NYI) */
+
+/* Registers 0x7000 - 0x7024 are NVM Interface registers (NYI) */
+
+
+/* PCI Capability registers (should be moved to PCI headers) */
+
+/* PCI-X Capability and Command Register (0x40) */
+
+#define PCIX_CMD_DPREC_ENABLE 0x00010000
+#define PCIX_CMD_RLXORDER_ENABLE 0x00020000
+#define PCIX_CMD_RD_CNT_SHIFT 18
+#define PCIX_CMD_RD_CNT_MASK 0x000C0000
+#define PCIX_CMD_MAX_SPLIT_SHIFT 20
+#define PCIX_CMD_MAX_SPLIT_MASK 0x00700000
+
+/* PCI-X Status Register (0x44) */
+
+
+/* Generic bit fields shared by most MODE and STATUS registers */
+
+#define M_MODE_RESET _DD_MAKEMASK1(0)
+#define M_MODE_ENABLE _DD_MAKEMASK1(1)
+#define M_MODE_ATTNENABLE _DD_MAKEMASK1(2)
+
+#define M_STAT_ERROR _DD_MAKEMASK1(1)
+
+/* Generic bit fields shared by STATS_CTRL registers */
+
+#define M_STATS_ENABLE _DD_MAKEMASK1(0)
+#define M_STATS_FASTUPDATE _DD_MAKEMASK1(1)
+#define M_STATS_CLEAR _DD_MAKEMASK1(2)
+#define M_STATS_FLUSH _DD_MAKEMASK1(3)
+#define M_STATS_ZERO _DD_MAKEMASK1(4)
+
+/* Private PCI Configuration registers (p 335) */
+
+/* MHC: Miscellaneous Host Control Register (0x68) */
+
+#define M_MHC_CLEARINTA _DD_MAKEMASK1(0)
+#define M_MHC_MASKPCIINT _DD_MAKEMASK1(1)
+#define M_MHC_ENBYTESWAP _DD_MAKEMASK1(2)
+#define M_MHC_ENWORDSWAP _DD_MAKEMASK1(3)
+#define M_MHC_ENPCISTATERW _DD_MAKEMASK1(4)
+#define M_MHC_ENCLKCTRLRW _DD_MAKEMASK1(5)
+#define M_MHC_ENREGWORDSWAP _DD_MAKEMASK1(6)
+#define M_MHC_ENINDIRECT _DD_MAKEMASK1(7)
+#define S_MHC_ASICREV 16
+#define M_MHC_ASICREV _DD_MAKEMASK(16,S_MHC_ASICREV)
+#define G_MHC_ASICREV(x) _DD_GETVALUE(x,S_MHC_ASICREV,M_MHC_ASICREV)
+
+/* DMAC: DMA Read/Write Control Register (0x6c) */
+
+#define S_DMAC_MINDMA 0
+#define M_DMAC_MINDMA _DD_MAKEMASK(8,S_DMAC_MINDMA)
+#define V_DMAC_MINDMA(x) _DD_MAKEVALUE(x,S_DMAC_MINDMA)
+#define G_DMAC_MINDMA(x) _DD_GETVALUE(x,S_DMAC_MINDMA,M_DMAC_MINDMA)
+
+#define M_DMAC_MEMRDMULT _DD_MAKEMASK1(22) /* 570{0,1} only */
+#define M_DMAC_BEALL _DD_MAKEMASK1(23) /* 570{0,1} only */
+
+#define S_DMAC_RDCMD 24 /* 570{0,1} only */
+#define M_DMAC_RDCMD _DD_MAKEMASK(4,S_DMAC_RDCMD)
+#define V_DMAC_RDCMD(x) _DD_MAKEVALUE(x,S_DMAC_RDCMD)
+#define G_DMAC_RDCMD(x) _DD_GETVALUE(x,S_DMAC_RDCMD,M_DMAC_RDCMD)
+#define K_PCI_MEMRD 0x6
+
+#define S_DMAC_WRCMD 28
+#define M_DMAC_WRCMD _DD_MAKEMASK(4,S_DMAC_WRCMD)
+#define V_DMAC_WRCMD(x) _DD_MAKEVALUE(x,S_DMAC_WRCMD)
+#define G_DMAC_WRCMD(x) _DD_GETVALUE(x,S_DMAC_WRCMD,M_DMAC_WRCMD)
+#define K_PCI_MEMWR 0x7
+
+/* PCIS: PCI State Register (0x70) */
+
+#define M_PCIS_RESET _DD_MAKEMASK1(0)
+#define M_PCIS_INT _DD_MAKEMASK1(1)
+#define M_PCIS_MODE _DD_MAKEMASK1(2)
+#define M_PCIS_33MHZ _DD_MAKEMASK1(3)
+#define M_PCIS_32BIT _DD_MAKEMASK1(4)
+#define M_PCIS_ROMEN _DD_MAKEMASK1(5)
+#define M_PCIS_ROMRETRY _DD_MAKEMASK1(6)
+#define M_PCIS_FLATVIEW _DD_MAKEMASK1(8)
+/* ... more ... */
+
+/* PCI Clock Control Register (0x74) */
+
+/* Register Base Address Register (0x78) */
+
+/* Memory Window Base Address Register (0x7c) */
+
+
+/* High Priority Mailboxes (p 323) */
+
+
+/* Ethernet MAC Control registers (p 358) */
+
+/* MACM: Ethernet MAC Mode Register (0x400) */
+
+#define M_MACM_GLBRESET _DD_MAKEMASK1(0)
+#define M_MACM_HALFDUPLEX _DD_MAKEMASK1(1)
+
+#define S_MACM_PORTMODE 2
+#define M_MACM_PORTMODE _DD_MAKEMASK(2,S_MACM_PORTMODE)
+#define V_MACM_PORTMODE(x) _DD_MAKEVALUE(x,S_MACM_PORTMODE)
+#define G_MACM_PORTMODE(x) _DD_GETVALUE(x,S_MACM_PORTMODE,M_MACM_PORTMODE)
+#define K_MACM_PORTMODE_NONE 0x0
+#define K_MACM_PORTMODE_MII 0x1
+#define K_MACM_PORTMODE_GMII 0x2
+#define K_MACM_PORTMODE_TBI 0x3
+
+#define M_MACM_LOOPBACK _DD_MAKEMASK1(4)
+#define M_MACM_TAGGEDMAC _DD_MAKEMASK1(7)
+#define M_MACM_TXBURST _DD_MAKEMASK1(8)
+#define M_MACM_MAXDEFER _DD_MAKEMASK1(9)
+#define M_MACM_LINKPOLARITY _DD_MAKEMASK1(10)
+#define M_MACM_RXSTATSENB _DD_MAKEMASK1(11)
+#define M_MACM_RXSTATSCLR _DD_MAKEMASK1(12)
+#define M_MACM_RXSTATSFLUSH _DD_MAKEMASK1(13)
+#define M_MACM_TXSTATSENB _DD_MAKEMASK1(14)
+#define M_MACM_TXSTATSCLR _DD_MAKEMASK1(15)
+#define M_MACM_TXSTATSFLUSH _DD_MAKEMASK1(16)
+#define M_MACM_SENDCFGS _DD_MAKEMASK1(17)
+#define M_MACM_MAGICPKT _DD_MAKEMASK1(18)
+#define M_MACM_ACPI _DD_MAKEMASK1(19)
+#define M_MACM_MIPENB _DD_MAKEMASK1(20)
+#define M_MACM_TDEENB _DD_MAKEMASK1(21)
+#define M_MACM_RDEENB _DD_MAKEMASK1(22)
+#define M_MACM_FHDEENB _DD_MAKEMASK1(23)
+
+/* MACSTAT: Ethernet MAC Status Register (0x404) */
+/* MACEVNT: Ethernet MAC Event Enable Register (0x408) */
+
+/* Status Register only */
+#define M_MACSTAT_PCSSYNC _DD_MAKEMASK1(0)
+#define M_MACSTAT_SIGDET _DD_MAKEMASK1(1)
+#define M_MACSTAT_RCVCFG _DD_MAKEMASK1(2)
+#define M_MACSTAT_CFGCHNG _DD_MAKEMASK1(3)
+#define M_MACSTAT_SYNCCHNG _DD_MAKEMASK1(4)
+/* Status and Enable Registers */
+#define M_EVT_PORTERR _DD_MAKEMASK1(10)
+#define M_EVT_LINKCHNG _DD_MAKEMASK1(12)
+#define M_EVT_MICOMPLETE _DD_MAKEMASK1(22)
+#define M_EVT_MIINT _DD_MAKEMASK1(23)
+#define M_EVT_APERR _DD_MAKEMASK1(24)
+#define M_EVT_ODIERR _DD_MAKEMASK1(25)
+#define M_EVT_RXSTATOVRUN _DD_MAKEMASK1(26)
+#define M_EVT_TXSTATOVRUN _DD_MAKEMASK1(27)
+
+/* MICOMM: MI Communication Register (0x44c) */
+
+#define S_MICOMM_DATA 0
+#define M_MICOMM_DATA _DD_MAKEMASK(16,S_MICOMM_DATA)
+#define V_MICOMM_DATA(x) _DD_MAKEVALUE(x,S_MICOMM_DATA)
+#define G_MICOMM_DATA(x) _DD_GETVALUE(x,S_MICOMM_DATA,M_MICOMM_DATA)
+
+#define S_MICOMM_REG 16
+#define M_MICOMM_REG _DD_MAKEMASK(5,S_MICOMM_REG)
+#define V_MICOMM_REG(x) _DD_MAKEVALUE(x,S_MICOMM_REG)
+#define G_MICOMM_REG(x) _DD_GETVALUE(x,S_MICOMM_REG,M_MICOMM_REG)
+
+#define S_MICOMM_PHY 21
+#define M_MICOMM_PHY _DD_MAKEMASK(5,S_MICOMM_PHY)
+#define V_MICOMM_PHY(x) _DD_MAKEVALUE(x,S_MICOMM_PHY)
+#define G_MICOMM_PHY(x) _DD_GETVALUE(x,S_MICOMM_PHY,M_MICOMM_PHY)
+
+#define S_MICOMM_CMD 26
+#define M_MICOMM_CMD _DD_MAKEMASK(2,S_MICOMM_CMD)
+#define V_MICOMM_CMD(x) _DD_MAKEVALUE(x,S_MICOMM_CMD)
+#define G_MICOMM_CMD(x) _DD_GETVALUE(x,S_MICOMM_CMD,M_MICOMM_CMD)
+#define K_MICOMM_CMD_WR 0x1
+#define K_MICOMM_CMD_RD 0x2
+#define V_MICOMM_CMD_WR V_MICOMM_CMD(K_MICOMM_CMD_WR)
+#define V_MICOMM_CMD_RD V_MICOMM_CMD(K_MICOMM_CMD_RD)
+
+#define M_MICOMM_RDFAIL _DD_MAKEMASK1(28)
+#define M_MICOMM_BUSY _DD_MAKEMASK1(29)
+
+/* MISTAT: MI Status Register (0x450) */
+
+#define M_MISTAT_LINKED _DD_MAKEMASK1(0)
+#define M_MISTAT_10MBPS _DD_MAKEMASK1(1)
+
+/* MIMODE: MI Mode Register (0x454) */
+
+#define M_MIMODE_SHORTPREAMBLE _DD_MAKEMASK1(1)
+#define M_MIMODE_POLLING _DD_MAKEMASK1(4)
+
+#define S_MIMODE_CLKCNT 16
+#define M_MIMODE_CLKCNT _DD_MAKEMASK(5,S_MIMODE_CLKCNT)
+#define V_MIMODE_CLKCNT(x) _DD_MAKEVALUE(x,S_MIMODE_CLKCNT)
+#define G_MIMODE_CLKCNT(x) _DD_GETVALUE(x,S_MIMODE_CLKCNT,M_MIMODE_CLKCNT)
+
+/* TXLEN: Transmit MAC Lengths Register (0x464) */
+
+#define S_TXLEN_SLOT 0
+#define M_TXLEN_SLOT _DD_MAKEMASK(8,S_TXLEN_SLOT)
+#define V_TXLEN_SLOT(x) _DD_MAKEVALUE(x,S_TXLEN_SLOT)
+#define G_TXLEN_SLOT(x) _DD_GETVALUE(x,S_TXLEN_SLOT,M_TXLEN_SLOT)
+
+#define S_TXLEN_IPG 8
+#define M_TXLEN_IPG _DD_MAKEMASK(4,S_TXLEN_IPG)
+#define V_TXLEN_IPG(x) _DD_MAKEVALUE(x,S_TXLEN_IPG)
+#define G_TXLEN_IPG(x) _DD_GETVALUE(x,S_TXLEN_IPG,M_TXLEN_IPG)
+
+#define S_TXLEN_IPGCRS 12
+#define M_TXLEN_IPGCRS _DD_MAKEMASK(2,S_TXLEN_IPGCRS)
+#define V_TXLEN_IPGCRS(x) _DD_MAKEVALUE(x,S_TXLEN_IPGCRS)
+#define G_TXLEN_IPGCRS(x) _DD_GETVALUE(x,S_TXLEN_IPGCRS,M_TXLEN_IPGCRS)
+
+/* RULESCFG: Receive Rules Configuration Register (0x500) */
+
+#define S_RULESCFG_DEFAULT 3
+#define M_RULESCFG_DEFAULT _DD_MAKEMASK(5,S_RULESCFG_DEFAULT)
+#define V_RULESCFG_DEFAULT(x) _DD_MAKEVALUE(x,S_RULESCFG_DEFAULT)
+#define G_RULESCFG_DEFAULT(x) _DD_GETVALUE(x,S_RULESCFG_DEFAULT,M_RULESCFG_DEFAULT)
+
+
+/* Send Data Initiator Control Registers (p 383) */
+/* Send BD Ring Selector Control Registers (p 387) */
+/* Send BD Initiator Control Registers (p 389) */
+
+
+/* Receive List Placement Control Registers (p 392) */
+
+/* LISTCFG: Receive List Placement Configuration Register (0x2010) */
+
+#define S_LISTCFG_GROUP 0
+#define M_LISTCFG_GROUP _DD_MAKEMASK(3,S_LISTCFG_GROUP)
+#define V_LISTCFG_GROUP(x) _DD_MAKEVALUE(x,S_LISTCFG_GROUP)
+#define G_LISTCFG_GROUP(x) _DD_GETVALUE(x,S_LISTCFG_GROUP,M_LISTCFG_GROUP)
+
+#define S_LISTCFG_ACTIVE 3
+#define M_LISTCFG_ACTIVE _DD_MAKEMASK(5,S_LISTCFG_ACTIVE)
+#define V_LISTCFG_ACTIVE(x) _DD_MAKEVALUE(x,S_LISTCFG_ACTIVE)
+#define G_LISTCFG_ACTIVE(x) _DD_GETVALUE(x,S_LISTCFG_ACTIVE,M_LISTCFG_ACTIVE)
+
+#define S_LISTCFG_BAD 8
+#define M_LISTCFG_BAD _DD_MAKEMASK(5,S_LISTCFG_BAD)
+#define V_LISTCFG_BAD(x) _DD_MAKEVALUE(x,S_LISTCFG_BAD)
+#define G_LISTCFG_BAD(x) _DD_GETVALUE(x,S_LISTCFG_BAD,M_LISTCFG_BAD)
+
+#define S_LISTCFG_DEFAULT 13
+#define M_LISTCFG_DEFAULT _DD_MAKEMASK(2,S_LISTCFG_DEFAULT)
+#define V_LISTCFG_DEFAULT(x) _DD_MAKEVALUE(x,S_LISTCFG_DEFAULT)
+#define G_LISTCFG_DEFAULT(x) _DD_GETVALUE(x,S_LISTCFG_DEFAULT,M_LISTCFG_DEFAULT)
+
+
+/* Receive Data and Receive BD Initiator Control Registers (p 399) */
+
+/* RCVINITMODE: Receive Data and Receive BD Initiator Mode Register (0x2400) */
+
+#define M_RCVINITMODE_JUMBO _DD_MAKEMASK1(2)
+#define M_RCVINITMODE_FRMSIZE _DD_MAKEMASK1(3)
+#define M_RCVINITMODE_RTNSIZE _DD_MAKEMASK1(4)
+
+
+/* Receive Initiator Control Registers (p 404) */
+/* Receive BD Completion Control Registers (p 406) */
+/* Receive List Selector Control Registers (p 408) */
+/* Mbuf Cluster Free Registers (p 409) */
+
+
+/* Host Coalescing Control registers (p 410) */
+
+/* HCM: Host Coalescing Mode Register (0x3C00) */
+
+#define M_HCM_RESET _DD_MAKEMASK1(0)
+#define M_HCM_ENABLE _DD_MAKEMASK1(1)
+#define M_HCM_ATTN _DD_MAKEMASK1(2)
+#define M_HCM_COAL_NOW _DD_MAKEMASK1(3)
+
+#define S_HCM_MSIBITS 4
+#define M_HCM_MSIBITS _DD_MAKEMASK(3,S_HCM_MSIBITS)
+#define V_HCM_MSIBITS(x) _DD_MAKEVALUE(x,S_HCM_MSIBITS)
+#define G_HCM_MSIBITS _DD_GETVALUE(x,S_HCM_MSIBITS,M_HCM_MSIBITS)
+
+#define S_HCM_SBSIZE 7
+#define M_HCM_SBSIZE _DD_MAKEMASK(2,S_HCM_SBSIZE)
+#define V_HCM_SBSIZE(x) _DD_MAKEVALUE(x,S_HCM_SBSIZE)
+#define G_HCM_SBSIZE _DD_GETVALUE(x,S_HCM_SBSIZE,M_HCM_SBSIZE)
+#define K_HCM_SBSIZE_80 0x0
+#define K_HCM_SBSIZE_64 0x1
+#define K_HCM_SBSIZE_32 0x2
+/* ... more ... */
+
+
+/* Memory Arbiter Registers (p 420) */
+
+/* MAM: Memory Arbiter Mode Register (0x4000) */
+
+#define M_MAM_RESET _DD_MAKEMASK1(0)
+#define M_MAM_ENABLE _DD_MAKEMASK1(1)
+
+/* Memory Arbiter Status Register (0x4004) */
+
+/* Memory Arbiter Trap Low and Trap High Registers (0x4008, 0x400C) */
+
+
+/* Buffer Manager Control Registers (p 424) */
+
+/* BMODE: Buffer Manager Control Register (0x4400) */
+
+#define M_BMODE_RESET _DD_MAKEMASK1(0)
+#define M_BMODE_ENABLE _DD_MAKEMASK1(1)
+#define M_BMODE_ATTN _DD_MAKEMASK1(2)
+#define M_BMODE_TEST _DD_MAKEMASK1(3)
+#define M_BMODE_MBUFLOWATTN _DD_MAKEMASK1(4)
+
+
+/* Read DMA Control Registers (p 428) */
+/* Write DMA Control Registers (p 431) */
+
+/* Bit fields shared by DMA_MODE and DMA_STATUS registers */
+
+#define M_ATTN_TGTABORT _DD_MAKEMASK1(2)
+#define M_ATTN_MSTRABORT _DD_MAKEMASK1(3)
+#define M_ATTN_PERR _DD_MAKEMASK1(4)
+#define M_ATTN_ADDROVFL _DD_MAKEMASK1(5)
+#define M_ATTN_FIFOOVFL _DD_MAKEMASK1(6)
+#define M_ATTN_FIFOUNFL _DD_MAKEMASK1(7)
+#define M_ATTN_FIFOREAD _DD_MAKEMASK1(8)
+#define M_ATTN_LENERR _DD_MAKEMASK1(9)
+#define M_ATTN_ALL (M_ATTN_TGTABORT | M_ATTN_MSTRABORT | \
+ M_ATTN_PERR | M_ATTN_ADDROVFL | \
+ M_ATTN_FIFOOVFL | M_ATTN_FIFOUNFL | \
+ M_ATTN_FIFOREAD | M_ATTN_LENERR)
+
+/* Read DMA Mode Register (0x4800) */
+/* Write DMA Mode Register (0x4C00) */
+
+/* Read DMA Status Register (0x4804) */
+/* Write DMA Status Register (0x4C04) */
+
+
+/* RX RISC Registers (p 433) */
+/* TX RISC Registers (p 437) */
+/* Low Priority Mailboxes (p 441) */
+/* Flow Through Queues (p 445) */
+/* Message Signaled Interrupt Registers (p 447) */
+/* DMA Completion Registers (p 449) */
+
+
+/* General Control registers (p 450) */
+
+/* MCTL: Miscellaneous Host Control Register (0x6800) */
+
+#define M_MCTL_UPDATE _DD_MAKEMASK1(0)
+#define M_MCTL_BSWAPCTRL _DD_MAKEMASK1(1)
+#define M_MCTL_WSWAPCTRL _DD_MAKEMASK1(2)
+#define M_MCTL_BSWAPDATA _DD_MAKEMASK1(4)
+#define M_MCTL_WSWAPDATA _DD_MAKEMASK1(5)
+#define M_MCTL_NOCRACK _DD_MAKEMASK1(9)
+#define M_MCTL_NOCRC _DD_MAKEMASK1(10)
+#define M_MCTL_ACCEPTBAD _DD_MAKEMASK1(11)
+#define M_MCTL_NOTXINT _DD_MAKEMASK1(13)
+#define M_MCTL_NORTRNINT _DD_MAKEMASK1(14)
+#define M_MCTL_PCI32 _DD_MAKEMASK1(15)
+#define M_MCTL_HOSTUP _DD_MAKEMASK1(16)
+#define M_MCTL_HOSTBDS _DD_MAKEMASK1(17)
+#define M_MCTL_NOTXPHSUM _DD_MAKEMASK1(20)
+#define M_MCTL_NORXPHSUM _DD_MAKEMASK1(23)
+#define M_MCTL_TXINT _DD_MAKEMASK1(24)
+#define M_MCTL_RXINT _DD_MAKEMASK1(25)
+#define M_MCTL_MACINT _DD_MAKEMASK1(26)
+#define M_MCTL_DMAINT _DD_MAKEMASK1(27)
+#define M_MCTL_FLOWINT _DD_MAKEMASK1(28)
+#define M_MCTL_4XRINGS _DD_MAKEMASK1(29)
+#define M_MCTL_MCASTEN _DD_MAKEMASK1(30)
+
+/* MCFG: Miscellaneous Configuration Register (0x6804) */
+
+#define M_MCFG_CORERESET _DD_MAKEMASK1(0)
+#define S_MCFG_PRESCALER 1
+#define M_MCFG_PRESCALER _DD_MAKEMASK(7,S_MCFG_PRESCALER)
+#define V_MCFG_PRESCALER(x) _DD_MAKEVALUE(x,S_MCFG_PRESCALER)
+#define G_MCFG_PRESCALER(x) _DD_GETVALUE(x,S_MCFG_PRESCALER,M_MCFG_PRESCALER)
+
+/* MLCTL: Miscellaneous Local Control Register (0x6808) */
+
+#define M_MLCTL_INTSTATE _DD_MAKEMASK1(0)
+#define M_MLCTL_INTCLR _DD_MAKEMASK1(1)
+#define M_MLCTL_INTSET _DD_MAKEMASK1(2)
+#define M_MLCTL_INTATTN _DD_MAKEMASK1(3)
+/* ... */
+#define M_MLCTL_EPAUTOACCESS _DD_MAKEMASK1(24)
+
+/* EPADDR: Serial EEPROM Address Register (0x6838) */
+
+#define S_EPADDR_ADDR 0
+#define M_EPADDR_ADDR (_DD_MAKEMASK(16,S_EPADDR_ADDR) & ~3)
+#define V_EPADDR_ADDR(x) _DD_MAKEVALUE(x,S_EPADDR_ADDR)
+#define G_EPADDR_ADDR(x) _DD_GETVALUE(x,S_EPADDR_ADDR,M_EPADDR_ADDR)
+
+#define S_EPADDR_HPERIOD 16
+#define M_EPADDR_HPERIOD _DD_MAKEMASK(9,S_EPADDR_HPERIOD)
+#define V_EPADDR_HPERIOD(x) _DD_MAKEVALUE(x,S_EPADDR_HPERIOD)
+#define G_EPADDR_HPERIOD(x) _DD_GETVALUE(x,S_EPADDR_HPERIOD,M_EPADDR_HPERIOD)
+
+#define M_EPADDR_START _DD_MAKEMASK1(25)
+
+#define S_EPADDR_DEVID 26
+#define M_EPADDR_DEVID _DD_MAKEMASK(3,S_EPADDR_DEVID)
+#define V_EPADDR_DEVID(x) _DD_MAKEVALUE(x,S_EPADDR_DEVID)
+#define G_EPADDR_DEVID(x) _DD_GETVALUE(x,S_EPADDR_DEVID,M_EPADDR_DEVID)
+
+#define M_EPADDR_RESET _DD_MAKEMASK1(29)
+#define M_EPADDR_COMPLETE _DD_MAKEMASK1(30)
+#define M_EPADDR_RW _DD_MAKEMASK1(31)
+
+/* EPDATA: Serial EEPROM Data Register (0x683C) */
+
+/* EPCTL: Serial EEPROM Control Register (0x6840) */
+
+#define M_EPCTL_CLOCKTS0 _DD_MAKEMASK1(0)
+#define M_EPCTL_CLOCKO _DD_MAKEMASK1(1)
+#define M_EPCTL_CLOCKI _DD_MAKEMASK1(2)
+#define M_EPCTL_DATATSO _DD_MAKEMASK1(3)
+#define M_EPCTL_DATAO _DD_MAKEMASK1(4)
+#define M_EPCTL_DATAI _DD_MAKEMASK1(5)
+
+/* MDCTL: MDI Control Register (0x6844) */
+
+#define M_MDCTL_DATA _DD_MAKEMASK1(0)
+#define M_MDCTL_ENABLE _DD_MAKEMASK1(1)
+#define M_MDCTL_SELECT _DD_MAKEMASK1(2)
+#define M_MDCTL_CLOCK _DD_MAKEMASK1(3)
+
+
+/* Ring Control Blocks (p 97) */
+
+#define RCB_HOST_ADDR_HIGH 0x0
+#define RCB_HOST_ADDR_LOW 0x4
+#define RCB_CTRL 0x8
+#define RCB_NIC_ADDR 0xC
+
+#define RCB_SIZE 0x10
+
+#define RCB_FLAG_USE_EXT_RCV_BD _DD_MAKEMASK1(0)
+#define RCB_FLAG_RING_DISABLED _DD_MAKEMASK1(1)
+
+#define S_RCB_MAXLEN 16
+#define M_RCB_MAXLEN _DD_MAKEMASK(16,S_RCB_MAXLEN)
+#define V_RCB_MAXLEN(x) _DD_MAKEVALUE(x,S_RCB_MAXLEN)
+#define G_RCB_MAXLEN(x) _DD_GETVALUE(x,S_RCB_MAXLEN,M_RCB_MAXLEN)
+
+
+/* On-chip Memory Map (Tables 70 and 71, pp 178-179) This is the map
+ for the 5700 with no external SRAM, the 5701, 5702 and 5703. The
+ 5705 does not fully implement some ranges and maps the buffer pool
+ differently. */
+
+/* Locations 0x0000 - 0x00FF are Page Zero */
+
+/* Locations 0x0100 - 0x01FF are Send Producer Ring RCBs */
+
+#define A_SND_RCBS 0x0100
+#define L_SND_RCBS (16*RCB_SIZE)
+#define A_SND_RCB(n) (A_SND_RCBS + ((n)-1)*RCB_SIZE)
+
+/* Locations 0x0200 - 0x02FF are Receive Return Ring RCBs */
+
+#define A_RTN_RCBS 0x0200
+#define L_RTN_RCBS (16*RCB_SIZE)
+#define A_RTN_RCB(n) (A_RTN_RCBS + ((n)-1)*RCB_SIZE)
+
+/* Locations 0x0300 - 0x0AFF are Statistics Block */
+
+#define A_MAC_STATS 0x0300
+#define L_MAC_STATS (0x0B00-A_MAC_STATS)
+
+/* Locations 0x0B00 - 0x0B4F are Status Block */
+
+#define A_MAC_STATUS 0x0B00
+#define L_MAC_STATUS (0x0B50-A_MAC_STATUS)
+
+/* Locations 0x0B50 - 0x0FFF are Software General Communication */
+
+#define A_PXE_MAILBOX 0x0B50
+#define T3_MAGIC_NUMBER 0x4B657654
+
+/* Locations 0x1000 - 0x1FFF are unmapped */
+
+/* Locations 0x2000 - 0x3FFF are DMA Descriptors */
+
+#define A_DMA_DESCS 0x2000
+#define L_DMA_DESCS (0x4000-A_DMA_DESCS)
+
+/* Locations 0x4000 - 0x5FFF are Send Rings 1-4 */
+
+#define A_SND_RINGS 0x4000
+#define L_SND_RINGS (0x6000-A_SND_RINGS)
+
+/* Locations 0x6000 - 0x6FFF are Standard Receive Rings */
+
+#define A_STD_RCV_RINGS 0x6000
+#define L_STD_RCV_RINGS (0x7000-A_STD_RCV_RINGS)
+
+/* Locations 0x7000 - 0x7FFF are Jumbo Receive Rings */
+
+#define A_JUMBO_RCV_RINGS 0x7000
+#define L_JUMBO_RCV_RINGS (0x8000-A_JUMBO_RCV_RINGS)
+
+/* Locations 0x08000 - 0x0FFFF are Buffer Pool 1 */
+/* Locations 0x10000 - 0x17FFF are Buffer Pool 2 */
+/* Locations 0x18000 - 0x1FFFF are Buffer Pool 3 */
+
+#define A_BUFFER_POOL 0x08000
+#define L_BUFFER_POOL (0x20000-A_BUFFER_POOL)
+
+/* Locations 0x08000 - 0x09FFF are TXMBUF (5705) */
+/* Locations 0x10000 - 0x1DFFF are RXMBUF (5705) */
+
+#define A_TXMBUF 0x080000
+#define L_TXMBUF (0x0A000-A_TXMBUF)
+#define A_RXMBUF 0x100000
+#define L_RXMBUF (0x1E000-A_RXMBUF)
+
+
+/* Indices of (8-byte) counters in the Statistics Block. */
+
+#define ifHCInOctets 32
+#define etherStatsFragments 34
+#define ifHCInUcastPkts 35
+#define ifHCInMulticastPkts 36
+#define ifHCInBroadcastPkts 37
+#define dot3StatsFCSErrors 38
+#define dot3StatsAlignmentErrors 39
+#define xonPauseFramesReceived 40
+#define xoffPauseFramesReceived 41
+#define macControlFramesReceived 42
+#define xoffSateEntered 43
+#define dot3StatsFrameTooLongs 44
+#define etherStatsJabbers 45
+#define etherStatsUndersizePkts 46
+#define inRangeLengthError 47
+#define outRangeLengthError 48
+#define etherStatsPkts64Octets 49
+#define etherStatsPkts65to127Octets 50
+#define etherStatsPkts128to255Octets 51
+#define etherStatsPkts256to511Octets 52
+#define etherStatsPkts512to1023Octets 53
+#define etherStatsPkts1024to1522Octets 54
+#define etherStatsPkts1523to2047Octets 55
+#define etherStatsPkts2048to4095Octets 56
+#define etherStatsPkts4096to8191Octets 57
+#define etherStatsPkts8192to9022Octets 58
+
+#define ifHCOutOctets 96
+#define etherStatsCollisions 98
+#define outXonSent 99
+#define outXoffSent 100
+#define flowControlDone 101
+#define dot3StatsInternalMacTransmitErrors 102
+#define dot3StatsSingleCollisionFrames 103
+#define dot3StatsMultipleCollisionFrames 104
+#define dot3StatsDeferredTransmissions 105
+#define dot3StatsExcessiveCollisions 107
+#define dot3StatsLateCollisions 108
+#define dot3Collided2Times 109
+#define dot3Collided3Times 110
+#define dot3Collided4Times 111
+#define dot3Collided5Times 112
+#define dot3Collided6Times 113
+#define dot3Collided7Times 114
+#define dot3Collided8Times 115
+#define dot3Collided9Times 116
+#define dot3Collided10Times 117
+#define dot3Collided11Times 118
+#define dot3Collided12Times 119
+#define dot3Collided13Times 120
+#define dot3Collided14Times 121
+#define dot3Collided15Times 122
+#define ifHCOutUcastPkts 123
+#define ifHCOutMulticastPkts 124
+#define ifHCOutBroadcastPkts 125
+#define dot3StatsCarrierSenseErrors 126
+#define ifOutDiscards 127
+#define ifOutErrors 128
+
+#define COSifHCInPkts1 160
+#define COSifHCInPkts2 161
+#define COSifHCInPkts3 162
+#define COSifHCInPkts4 163
+#define COSifHCInPkts5 164
+#define COSifHCInPkts6 165
+#define COSifHCInPkts7 166
+#define COSifHCInPkts8 167
+#define COSifHCInPkts9 168
+#define COSifHCInPkts10 169
+#define COSifHCInPkts11 170
+#define COSifHCInPkts12 171
+#define COSifHCInPkts13 172
+#define COSifHCInPkts14 173
+#define COSifHCInPkts15 174
+#define COSifHCInPkts16 175
+#define COSFramesDroppedDueToFilters 176
+#define nicDmaWriteQueueFull 177
+#define nicDmaWriteHighPriQueueFull 178
+#define nicNoMoreRxBDs 179
+#define ifInDiscards 180
+#define ifInErrors 181
+#define nicRecvThresholdHit 182
+
+#define COSifHCOutPkts1 192
+#define COSifHCOutPkts2 193
+#define COSifHCOutPkts3 194
+#define COSifHCOutPkts4 195
+#define COSifHCOutPkts5 196
+#define COSifHCOutPkts6 197
+#define COSifHCOutPkts7 198
+#define COSifHCOutPkts8 199
+#define COSifHCOutPkts9 200
+#define COSifHCOutPkts10 201
+#define COSifHCOutPkts11 202
+#define COSifHCOutPkts12 203
+#define COSifHCOutPkts13 204
+#define COSifHCOutPkts14 205
+#define COSifHCOutPkts15 206
+#define COSifHCOutPkts16 207
+#define nicDmaReadQueueFull 208
+#define nicDmaReadHighPriQueueFull 209
+#define nicSendDataCompQueueFull 210
+#define nicRingSetSendProdIndex 211
+#define nicRingStatusUpdate 212
+#define nicInterrupts 213
+#define nicAvoidedInterrupts 214
+#define nicSendThresholdHit 215
+
+#endif /* _BCM_5700_H_ */
diff --git a/cfe/cfe/dev/bcm5821.h b/cfe/cfe/dev/bcm5821.h
new file mode 100644
index 0000000..29ece60
--- /dev/null
+++ b/cfe/cfe/dev/bcm5821.h
@@ -0,0 +1,278 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * BCM5821 cryptoaccelerator File: bcm5821.h
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifndef _BCM5821_H_
+#define _BCM5821_H_
+
+/* Register and field definitions for the Broadcom BCM5821 crypto
+ accelerator. The BCM5820 implements a compatible (modulo bugs)
+ subset of the BCM5821. */
+
+#define K_PCI_VENDOR_BROADCOM 0x14e4
+#define K_PCI_ID_BCM5820 0x5820
+#define K_PCI_ID_BCM5821 0x5821
+
+#define _DD_MAKEMASK1(n) (1 << (n))
+#define _DD_MAKEMASK(v,n) ((((1)<<(v))-1) << (n))
+#define _DD_MAKEVALUE(v,n) ((v) << (n))
+#define _DD_GETVALUE(v,n,m) (((v) & (m)) >> (n))
+
+
+/* DMA Control and Status Register offsets */
+
+#define R_MCR1 0x00
+#define R_DMA_CTRL 0x04
+#define R_DMA_STAT 0x08
+#define R_DMA_ERR 0x0C
+#define R_MCR2 0x10
+
+
+/* 0x00 MCR1@: Master Command Record 1 Address */
+/* 0x10 MCR2@: Master Command Record 2 Address */
+
+
+/* 0x04 DMA Control */
+
+#define M_DMA_CTRL_WR_BURST _DD_MAKEMASK1(16) /* Not 5820 */
+
+#define K_DMA_WR_BURST_128 0
+#define K_DMA_WR_BURST_240 M_DMA_CRTL_WR_BURST
+
+#define M_DMA_CTRL_MOD_NORM _DD_MAKEMASK1(22)
+#define M_DMA_CTRL_RNG_MODE _DD_MAKEMASK1(23)
+#define M_DMA_CTRL_DMAERR_EN _DD_MAKEMASK1(25)
+#define M_DMA_CTRL_NORM_PCI _DD_MAKEMASK1(26) /* Not 5820 */
+#define M_DMA_CTRL_LE_CRYPTO _DD_MAKEMASK1(27) /* Not 5820 */
+#define M_DMA_CTRL_MCR1_INT_EN _DD_MAKEMASK1(29)
+#define M_DMA_CTRL_MCR2_INT_EN _DD_MAKEMASK1(30)
+#define M_DMA_CTRL_RESET _DD_MAKEMASK1(31)
+
+
+/* 0x08 DMA Status */
+
+#define M_DMA_STAT_MCR2_EMPTY _DD_MAKEMASK1(24) /* Not 5820 */
+#define M_DMA_STAT_MCR1_EMPTY _DD_MAKEMASK1(25) /* Not 5820 */
+#define M_DMA_STAT_MCR2_INTR _DD_MAKEMASK1(26)
+#define M_DMA_STAT_MCR2_FULL _DD_MAKEMASK1(27)
+#define M_DMA_STAT_DMAERR_INTR _DD_MAKEMASK1(28)
+#define M_DMA_STAT_MCR1_INTR _DD_MAKEMASK1(29)
+#define M_DMA_STAT_MCR1_FULL _DD_MAKEMASK1(30)
+#define M_DMA_STAT_MSTR_ACCESS _DD_MAKEMASK1(31)
+
+/* 0x0C DMA Error Address */
+
+#define M_DMA_ERR_RD_FAULT _DD_MAKEMASK1(1)
+#define M_DMA_ERR_ADDR 0xFFFFFFFC
+
+
+/* Master Command Record Header Format */
+
+#define S_MCR_NUM_PACKETS 0
+#define M_MCR_NUM_PACKETS _DD_MAKEMASK(16,S_MCR_NUM_PACKETS)
+#define V_MCR_NUM_PACKETS(x) _DD_MAKEVALUE(x,S_MCR_NUM_PACKETS)
+#define G_MCR_NUM_PACKETS(x) _DD_GETVALUE(x,S_MCR_NUM_PACKETS,M_MCR_NUM_PACKETS)
+
+/* Input flags */
+
+#define M_MCR_SUPPRESS_INTR _DD_MAKEMASK1(31)
+
+/* Output flags */
+
+#define M_MCR_DONE _DD_MAKEMASK1(16)
+#define M_MCR_ERROR _DD_MAKEMASK1(17)
+
+#define S_MCR_ERROR_CODE 24
+#define M_MCR_ERROR_CODE _DD_MAKEMASK(8,S_MCR_ERROR_CODE)
+#define V_MCR_ERROR_CODE(x) _DD_MAKEVALUE(x,S_MCR_ERROR_CODE)
+#define G_MCR_ERROR_CODE(x) _DD_GETVALUE(x,S_MCR_ERROR_CODE,M_MCR_ERROR_CODE)
+#define K_MCR_ERROR_OK 0
+#define K_MCR_ERROR_UNKNOWN_OP 1
+#define K_MCR_ERROR_DSA_SHORT 2
+#define K_MCR_ERROR_PKI_SHORT 3
+#define K_MCR_ERROR_PKO_SHORT 4 /* Not 5820 */
+#define K_MCR_ERROR_CHAIN_SHORT 5 /* Not 5820 */
+#define K_MCR_ERROR_FIFO 6 /* Not 5820 */
+
+/* In both cases, the header word is followed by an array of N PD entries:
+ commandContext[0]
+ dataBuffer[0]
+ pktLen[0]
+ outputBuffer[0]
+ ...
+ commandContext[n-1]
+ dataBuffer[n-1]
+ pktLen[n-1]
+ outputBuffer[n-1]
+*/
+
+#define MCR_WORDS(n) (1+8*(n))
+#define MCR_BYTES(n) ((1+8*(n))*4)
+
+
+/* Data Buffer Chain Entry Offsets */
+
+#define DBC_ADDR 0
+#define DBC_NEXT 4
+#define DBC_LEN 8
+
+#define CHAIN_WORDS 3
+
+#define S_DBC_DATA_LEN 0
+#define M_DBC_DATA_LEN _DD_MAKEMASK(16,S_DBC_DATA_LEN)
+#define V_DBC_DATA_LEN(x) _DD_MAKEVALUE(x,S_DBC_DATA_LEN)
+#define G_DBC_DATA_LEN(x) _DD_GETVALUE(x,S_DBC_DATA_LEN,M_DBC_DATA_LEN)
+
+/* Packet Descriptor Offsets */
+
+#define PD_CC_ADDR 0
+#define PD_INPUT_FRAG 4
+#define PD_INPUT_FRAG_ADDR (PD_INPUT_FRAG+DBC_ADDR)
+#define PD_INPUT_FRAG_NEXT (PD_INPUT_FRAG+DBC_NEXT)
+#define PD_INPUT_FRAG_LEN (PD_INPUT_FRAG+DBC_LEN)
+#define PD_PKT_LEN 16
+#define PD_OUTPUT_FRAG 20
+#define PD_OUTPUT_FRAG_ADDR (PD_OUTPUT_FRAG+DBC_ADDR)
+#define PD_OUTPUT_FRAG_NEXT (PD_OUTPUT_FRAG+DBC_NEXT)
+#define PD_OUTPUT_FRAG_LEN (PD_OUTPUT_FRAG+DBC_LEN)
+
+#define PD_SIZE 32
+
+#define S_PD_PKT_LEN 16
+#define M_PD_PKT_LEN _DD_MAKEMASK(16,S_PD_PKT_LEN)
+#define V_PD_PKT_LEN(x) _DD_MAKEVALUE(x,S_PD_PKT_LEN)
+#define G_PD_PKT_LEN(x) _DD_GETVALUE(x,S_PD_PKT_LEN,M_PD_PKT_LEN)
+
+
+/* Crypotographic Operations */
+
+/* MCR1 only (symmetric) */
+#define K_IPSEC_3DES 0x0000 /* Not 5820 */
+#define K_SSL_MAC 0x0001
+#define K_TLS_HMAC 0x0002
+#define K_SSL_3DES 0x0003
+#define K_ARC4 0x0004
+#define K_HASH 0x0005
+
+/* MCR2 only (asymmetric) */
+#define K_DH_PK_GEN 0x0001
+#define K_DH_SK_GEN 0x0002
+#define K_RSA_PK_OP 0x0003
+#define K_RSA_SK_OP 0x0004
+#define K_DSA_SIGN 0x0005
+#define K_DSA_VERIF 0x0006
+#define K_RNG_DIRECT 0x0041
+#define K_RNG_SHA1 0x0042
+#define K_MOD_ADD 0x0043
+#define K_MOD_SUB 0x0044
+#define K_MOD_MUL 0x0045
+#define K_MOD_REDUCE 0x0046
+#define K_MOD_EXP 0x0047
+#define K_MOD_INV 0x0048 /* Not 5821 */
+#define K_MOD_2EXP 0x0049 /* Not 5820 */
+
+
+/* Command Context Header */
+
+/* Word 0 */
+
+#define S_CC_OPCODE 16
+#define M_CC_OPCODE _DD_MAKEMASK(16,S_CC_OPCODE)
+#define V_CC_OPCODE(x) _DD_MAKEVALUE(x,S_CC_OPCODE)
+#define G_CC_OPCODE(x) _DD_GETVALUE(x,S_CC_OPCODE,M_CC_OPCODE)
+
+#define S_CC_LEN 0
+#define M_CC_LEN _DD_MAKEMASK(16,S_CC_LEN)
+#define V_CC_LEN(x) _DD_MAKEVALUE(x,S_CC_LEN)
+#define G_CC_LEN(x) _DD_GETVALUE(x,S_CC_LEN,M_CC_LEN)
+
+/* Word 1 */
+
+#define S_CC_FLAGS 12
+#define M_CC_FLAGS _DD_MAKEMASK(4,S_CC_FLAGS)
+#define V_CC_FLAGS(x) _DD_MAKEVALUE(x,S_CC_FLAGS)
+#define G_CC_FLAGS(x) _DD_GETVALUE(x,S_CC_OPCODE,M_CC_OPCODE)
+
+/* The remaining command context fields depend on the opcode. */
+
+/* IPSEC 3DES (K_IPSEC_3DES) */
+
+/* SSL MAC (K_SSL_MAC) */
+/* TLS HMAC (K_TLS_HMAC) */
+/* Pure MD5/SHA-1 Hash (K_HASH) */
+
+#define K_HASH_FLAGS_MD5 1
+#define K_HASH_FLAGS_SHA1 2
+
+/* SSL MAC (K_SSL_MAC) */
+
+#define SSL_MAC_CMD_WORDS 22
+
+/* TLS HMAC (K_TLS_HMAC) */
+
+#define TLS_HMAC_CMD_WORDS 16
+
+/* Pure MD5/SHA-1 Hash (K_HASH) */
+
+/* SSL/TLS DES/3DES (K_SSL_3DES) */
+
+/* ARCFOUR (K_ARC4) */
+
+#define ARC4_STATE_WORDS (1 + 256/4)
+#define ARC4_CMD_WORDS (2 + ARC4_STATE_WORDS)
+
+#define M_ARC4_FLAGS_KEY _DD_MAKEMASK1(10)
+#define M_ARC4_FLAGS_WRITEBACK _DD_MAKEMASK1(11)
+#define M_ARC4_FLAGS_NULLDATA _DD_MAKEMASK1(12)
+
+
+/* Random number generation (K_RNG_DIRECT, K_RNG_SHA1) */
+
+/* Modular arithmetic (K_MOD_ADD, K_MOD_SUB, K_MOD_MUL) */
+
+/* Modular Remainder (K_MOD_REDUCE) */
+
+/* Modular Exponentiation (K_MOD_EXP) */
+
+/* Double Modular Exponentiation (K_MOD_2EXP) */
+
+
+#endif /* _BCM_5821_H_ */
diff --git a/cfe/cfe/dev/dc21143.h b/cfe/cfe/dev/dc21143.h
new file mode 100644
index 0000000..65f3255
--- /dev/null
+++ b/cfe/cfe/dev/dc21143.h
@@ -0,0 +1,588 @@
+/*
+ * Register and bit definitions for the DEC/Intel 21143 Ethernet controller,
+ * part of the Tulip family of 10 and 10/100 controllers.
+ * Reference:
+ * 21143 PCI/CardBus 10/100 Mb/s Ethernet LAN Controller,
+ * Hardware Reference Manual, Revision 1.0.
+ * Document No. 278074-001
+ * Intel Corp., October 1998
+ * Includes extensions/alternatives for the DEC 21040, 21041 and 21140(A)
+ * Ethernet controllers.
+ */
+#ifndef _DC21143_H_
+#define _DC21143_H_
+
+#define _DD_MAKEMASK1(n) (1 << (n))
+#define _DD_MAKEMASK(v,n) ((((1)<<(v))-1) << (n))
+#define _DD_MAKEVALUE(v,n) ((v) << (n))
+#define _DD_GETVALUE(v,n,m) (((v) & (m)) >> (n))
+
+
+/* *********************************************************************
+ * PCI Configuration Register offsets (Tulip nomenclature)
+ ********************************************************************* */
+
+#define R_CFG_CFID PCI_ID_REG
+#define K_PCI_VENDOR_DEC 0x1011
+#define K_PCI_ID_DC21040 0x0002
+#define K_PCI_ID_DC21041 0x0014
+#define K_PCI_ID_DC21140 0x0009
+#define K_PCI_ID_DC21143 0x0019
+
+#define R_CFG_CFRV PCI_CLASS_REG
+
+#define R_CFG_CBIO PCI_MAPREG(0)
+#define R_CFG_CBMA PCI_MAPREG(1)
+
+#define R_CFG_CFIT PCI_BPARAM_INTERRUPT_REG
+
+/* Tulip extensions */
+#define R_CFG_CFDD 0x40
+
+#define M_CFDD_SLEEP __DD_MAKEMASK1(31)
+#define M_CFDD_SNOOZE __DD_MAKEMASK1(30)
+
+#define R_CFG_CPMS 0xE0
+
+
+/* *********************************************************************
+ * CSRs: offsets
+ ********************************************************************* */
+
+#define R_CSR_BUSMODE 0x00
+#define R_CSR_TXPOLL 0x08
+#define R_CSR_RXPOLL 0x10
+#define R_CSR_RXRING 0x18
+#define R_CSR_TXRING 0x20
+#define R_CSR_STATUS 0x28
+#define R_CSR_OPMODE 0x30
+#define R_CSR_INTMASK 0x38
+#define R_CSR_MISSEDFRAME 0x40
+#define R_CSR_ROM_MII 0x48
+#define R_CSR_BOOTROM_ADRR 0x50
+#define R_CSR_GENTIMER 0x58
+
+/* The following registers are specific to the 21040 */
+
+#define R_CSR_FDUPLEX 0x58
+
+/* The following registers are specific to the 21040/21041 and 21142/21143 */
+
+#define R_CSR_SIASTATUS 0x60
+#define R_CSR_SIAMODE0 0x68
+#define R_CSR_SIAMODE1 0x70
+#define R_CSR_SIAMODE2 0x78
+
+/* The following registers are specific to the 21140/21140A */
+
+#define R_CSR_GENPORT 0x60
+#define R_CSR_WATCHDOG_TIMER 0x78
+
+
+/* CSR0: Bus Mode register */
+
+#define M_CSR0_SWRESET _DD_MAKEMASK1(0)
+#define M_CSR0_BUSARB _DD_MAKEMASK1(1)
+
+#define S_CSR0_SKIPLEN 2
+#define M_CSR0_SKIPLEN _DD_MAKEMASK(5,S_CSR0_SKIPLEN)
+#define V_CSR0_SKIPLEN(x) _DD_MAKEVALUE(x,S_CSR0_SKIPLEN)
+#define G_CSR0_SKIPLEN(x) _DD_GETVALUE(x,S_CSR0_SKIPLEN,M_CSR0_SKIPLEN)
+
+#define M_CSR0_BIGENDIAN _DD_MAKEMASK1(7)
+
+#define S_CSR0_BURSTLEN 8
+#define M_CSR0_BURSTLEN _DD_MAKEMASK(6,S_CSR0_BURSTLEN)
+#define V_CSR0_BURSTLEN(x) _DD_MAKEVALUE(x,S_CSR0_BURSTLEN)
+#define G_CSR0_BURSTLEN(x) _DD_GETVALUE(x,S_CSR0_BURSTLEN,M_CSR0_BURSTLEN)
+
+#define S_CSR0_CACHEALIGN 14
+#define M_CSR0_CACHEALIGN _DD_MAKEMASK(2,S_CSR0_CACHEALIGN)
+#define V_CSR0_CACHEALIGN(x) _DD_MAKEVALUE(x,S_CSR0_CACHEALIGN)
+#define G_CSR0_CACHEALIGN(x) _DD_GETVALUE(x,S_CSR0_CACHEALIGN,M_CSR0_CACHEALIGN)
+
+#define S_CSR0_TXAUTOPOLL 17
+#define M_CSR0_TXAUTOPOLL _DD_MAKEMASK(3,S_CSR0_AUTOPOLL)
+#define V_CSR0_TXAUTOPOLL(x) _DD_MAKEVALUE(x,S_CSR0_TXAUTOPOLL)
+#define G_CSR0_TXAUTOPOLL(x) _DD_GETVALUE(x,S_CSR0_TXAUTOPOLL,M_CSR0_TXAUTOPOLL)
+
+#define M_CSR0_DESCBYTEORDER _DD_MAKEMASK1(20) /* not 21040 */
+#define M_CSR0_READMULTENAB _DD_MAKEMASK1(21) /* not 2104{0,1} */
+#define M_CSR0_READLINEENAB _DD_MAKEMASK1(23) /* not 2104{0,1} */
+#define M_CSR0_WRITEINVALENAB _DD_MAKEMASK1(24) /* not 2104{0,1} */
+
+#define K_CSR0_TAPDISABLED 0x00
+#define K_CSR0_TAP200US 0x01
+#define K_CSR0_TAP800US 0x02
+#define K_CSR0_TAP1600US 0x03
+
+#define K_CSR0_ALIGNNONE 0
+#define K_CSR0_ALIGN32 1
+#define K_CSR0_ALIGN64 2
+#define K_CSR0_ALIGN128 3
+
+#define K_CSR0_BURST32 32
+#define K_CSR0_BURST16 16
+#define K_CSR0_BURST8 8
+#define K_CSR0_BURST4 4
+#define K_CSR0_BURST2 2
+#define K_CSR0_BURST1 1
+
+
+#define M_CSR3_RXDSCRADDR 0xFFFFFFFC
+#define M_CSR4_TXDSCRADDR 0xFFFFFFFC
+
+
+/* CSR5: Status register */
+
+#define M_CSR5_TXINT _DD_MAKEMASK1(0)
+#define M_CSR5_TXSTOP _DD_MAKEMASK1(1)
+#define M_CSR5_TXBUFUNAVAIL _DD_MAKEMASK1(2)
+#define M_CSR5_TXJABTIMEOUT _DD_MAKEMASK1(3)
+#define M_CSR5_LINKPASS _DD_MAKEMASK1(4) /* not 21040 */
+#define M_CSR5_TXUNDERFLOW _DD_MAKEMASK1(5)
+#define M_CSR5_RXINT _DD_MAKEMASK1(6)
+#define M_CSR5_RXBUFUNAVAIL _DD_MAKEMASK1(7)
+#define M_CSR5_RXSTOPPED _DD_MAKEMASK1(8)
+#define M_CSR5_RXWDOGTIMEOUT _DD_MAKEMASK1(9)
+#define M_CSR5_AUITPPIN _DD_MAKEMASK1(10) /* 21040 only */
+#define M_CSR5_TXEARLYINT _DD_MAKEMASK1(10) /* not 2104{0,1} */
+#define M_CSR5_FDSHORTFRAME _DD_MAKEMASK1(11) /* 21040 only */
+#define M_CSR5_GPTIMEREXPIRE _DD_MAKEMASK1(11) /* not 21040 */
+#define M_CSR5_LINKFAIL _DD_MAKEMASK1(12)
+#define M_CSR5_FATALBUSERROR _DD_MAKEMASK1(13)
+#define M_CSR5_RXEARLYINT _DD_MAKEMASK1(14) /* not 21040 */
+#define M_CSR5_ABNORMALINT _DD_MAKEMASK1(15)
+#define M_CSR5_NORMALINT _DD_MAKEMASK1(16)
+
+#define S_CSR5_RXPROCSTATE 17
+#define M_CSR5_RXPROCSTATE _DD_MAKEMASK(3,S_CSR5_RXPROCSTATE)
+#define V_CSR5_RXPROCSTATE(x) _DD_MAKEVALUE(x,S_CSR5_RXPROCSTATE)
+#define G_CSR5_RXPROCSTATE(x) _DD_GETVALUE(x,S_CSR5_RXPROCSTATE,M_CSR5_RXPROCSTATE)
+
+#define K_CSR5_RXSTOPPED 0x00 /* RESET or STOP command */
+#define K_CSR5_RXFETCH 0x01 /* fetching rx desc */
+#define K_CSR5_RXCHECK 0x02 /* checking end of rx pkt */
+#define K_CSR5_RXWAIT 0x03 /* waiting for rx pkt */
+#define K_CSR5_RXSUSPEND 0x04 /* unavailable rx buffer */
+#define K_CSR5_RXCLOSE 0x05 /* closing rx desc */
+#define K_CSR5_RXFLUSH 0x06 /* flushing rx frame */
+#define K_CSR5_RXQUEUE 0x07 /* reading rx frame from FIFO */
+
+#define S_CSR5_TXPROCSTATE 20
+#define M_CSR5_TXPROCSTATE _DD_MAKEMASK(3,S_CSR5_TXPROCSTATE)
+#define V_CSR5_TXPROCSTATE(x) _DD_MAKEVALUE(x,S_CSR5_TXPROCSTATE)
+#define G_CSR5_TXPROCSTATE(x) _DD_GETVALUE(x,S_CSR5_TXPROCSTATE,M_CSR5_TXPROCSTATE)
+
+#define K_CSR5_TXSTOPPED 0x00 /* RESET or STOP command */
+#define K_CSR5_TXFETCH 0x01 /* fetching tx desc */
+#define K_CSR5_TXWAIT 0x02 /* waiting for end of tx */
+#define K_CSR5_TXREAD 0x03 /* reading buffer into FIFO */
+#define K_CSR5_TXSETUP 0x05 /* setup packet */
+#define K_CSR5_TXSUSPEND 0x06 /* tx underflow or no tx desc */
+#define K_CSR5_TXCLOSE 0x07 /* closing tx desc */
+
+#define S_CSR5_ERRORBITS 23
+#define M_CSR5_ERRORBITS _DD_MAKEMASK(3,S_CSR5_ERRORBITS)
+#define V_CSR5_ERRORBITS(x) _DD_MAKEVALUE(x,S_CSR5_ERRORBITS)
+#define G_CSR5_ERRORBITS(x) _DD_GETVALUE(x,S_CSR5_ERRORBITS,M_CSR5_ERRORBITS)
+
+#define K_CSR5_FBE_PARITY 0x00
+#define K_CSR5_FBE_MABORT 0x01
+#define K_CSR5_FBE_TABORT 0x02
+
+#define M_CSR5_GPPORTINT _DD_MAKEMASK1(26) /* not 2104{0,1} */
+#define M_CSR5_LINKCHANGED _DD_MAKEMASK1(27) /* not 2104{0,1} */
+
+
+/* CSR6: Operating Mode register */
+
+#define M_CSR6_RXHASHFILT _DD_MAKEMASK1(0)
+#define M_CSR6_RXSTART _DD_MAKEMASK1(1)
+#define M_CSR6_HASHONLY _DD_MAKEMASK1(2)
+#define M_CSR6_PASSBADFRAMES _DD_MAKEMASK1(3)
+#define M_CSR6_INVERSEFILT _DD_MAKEMASK1(4)
+#define M_CSR6_STOPBACKOFF _DD_MAKEMASK1(5)
+#define M_CSR6_PROMISCUOUS _DD_MAKEMASK1(6)
+#define M_CSR6_PASSALLMULTI _DD_MAKEMASK1(7)
+#define M_CSR6_FULLDUPLEX _DD_MAKEMASK1(9)
+
+#define M_CSR6_INTLOOPBACK _DD_MAKEMASK1(10)
+#define M_CSR6_EXTLOOPBACK _DD_MAKEMASK1(11)
+
+#define S_CSR6_OPMODE 10
+#define M_CSR6_OPMODE _DD_MAKEMASK(2,S_CSR6_OPMODE)
+#define V_CSR6_OPMODE(x) _DD_MAKEVALUE(x,S_CSR6_OPMODE)
+#define G_CSR6_OPMODE(x) _DD_GETVALUE(x,S_CSR6_OPMODE,M_CSR6_OPMODE)
+
+#define M_CSR6_FORCECOLL _DD_MAKEMASK1(12)
+#define M_CSR6_TXSTART _DD_MAKEMASK1(13)
+
+#define S_CSR6_THRESHCONTROL 14
+#define M_CSR6_THRESHCONTROL _DD_MAKEMASK(2,S_CSR6_THRESHCONTROL)
+#define V_CSR6_THRESHCONTROL(x) _DD_MAKEVALUE(x,S_CSR6_THRESHCONTROL)
+#define G_CSR6_THRESHCONTROL(x) _DD_GETVALUE(x,S_CSR6_THRESHCONTROL,M_CSR6_THRESHCONTROL)
+
+#define M_CSR6_BACKPRESSURE _DD_MAKEMASK1(16) /* 21040 only */
+#define M_CSR6_CAPTUREEFFECT _DD_MAKEMASK1(17)
+
+#define M_CSR6_PORTSEL _DD_MAKEMASK1(18) /* not 2104{0,1} */
+#define M_CSR6_HBDISABLE _DD_MAKEMASK1(19) /* not 2104{0,1} */
+#define M_CSR6_STOREFWD _DD_MAKEMASK1(21) /* not 2104{0,1} */
+#define M_CSR6_TXTHRESH _DD_MAKEMASK1(22) /* not 2104{0,1} */
+#define M_CSR6_PCSFUNC _DD_MAKEMASK1(23) /* not 2104{0,1} */
+#define M_CSR6_SCRAMMODE _DD_MAKEMASK1(24) /* not 2104{0,1} */
+#define M_CSR6_MBO _DD_MAKEMASK1(25) /* not 2104{0,1} */
+#define M_CSR6_RXALL _DD_MAKEMASK1(30) /* not 2104{0,1} */
+
+#define M_CSR6_SPECCAP _DD_MAKEMASK1(31) /* not 21040 */
+
+#define K_CSR6_TXTHRES_128_72 0x00
+#define K_CSR6_TXTHRES_256_96 0x01
+#define K_CSR6_TXTHRES_512_128 0x02
+#define K_CSR6_TXTHRES_1024_160 0x03
+
+
+#define M_CSR6_SPEED_10 (M_CSR6_TXTHRESH)
+
+#define M_CSR6_SPEED_100 (M_CSR6_HBDISABLE | \
+ M_CSR6_SCRAMMODE | \
+ M_CSR6_PCSFUNC | \
+ M_CSR6_PORTSEL)
+
+#define M_CSR6_SPEED_10_MII (M_CSR6_TXTHRESH | \
+ M_CSR6_PORTSEL)
+
+#define M_CSR6_SPEED_100_MII (M_CSR6_HBDISABLE | \
+ M_CSR6_PORTSEL)
+
+
+/* CSR7: Interrupt mask register */
+
+#define M_CSR7_TXINT _DD_MAKEMASK1(0)
+#define M_CSR7_TXSTOP _DD_MAKEMASK1(1)
+#define M_CSR7_TXBUFUNAVAIL _DD_MAKEMASK1(2)
+#define M_CSR7_TXJABTIMEOUT _DD_MAKEMASK1(3)
+#define M_CSR7_LINKPASS _DD_MAKEMASK1(4) /* not 21040 */
+#define M_CSR7_TXUNDERFLOW _DD_MAKEMASK1(5)
+#define M_CSR7_RXINT _DD_MAKEMASK1(6)
+#define M_CSR7_RXBUFUNAVAIL _DD_MAKEMASK1(7)
+#define M_CSR7_RXSTOPPED _DD_MAKEMASK1(8)
+#define M_CSR7_RXWDOGTIMEOUT _DD_MAKEMASK1(9)
+#define M_CSR7_AUITPSW _DD_MAKEMASK1(10) /* 21040 only */
+#define M_CSR7_TXEARLY _DD_MAKEMASK1(10) /* not 2104{0,1} */
+#define M_CSR7_FD _DD_MAKEMASK1(11) /* 21040 only */
+#define M_CSR7_GPTIMER _DD_MAKEMASK1(11) /* not 21040 */
+#define M_CSR7_LINKFAIL _DD_MAKEMASK1(12)
+#define M_CSR7_FATALBUSERROR _DD_MAKEMASK1(13)
+#define M_CSR7_RXEARLY _DD_MAKEMASK1(14) /* not 21040 */
+#define M_CSR7_ABNORMALINT _DD_MAKEMASK1(15)
+#define M_CSR7_NORMALINT _DD_MAKEMASK1(16)
+#define M_CSR7_GPPORT _DD_MAKEMASK1(26) /* not 2104{0,1} */
+#define M_CSR7_LINKCHANGED _DD_MAKEMASK1(27) /* not 2104{0,1} */
+
+
+/* CSR8: Missed Frame register */
+
+#define M_CSR8_RXOVER_WRAP _DD_MAKEMASK1(28) /* not 2104{0,1} */
+#define S_CSR8_RXOVER 17
+#define M_CSR8_RXOVER _DD_MAKEMASK(11,S_CSR8_RXOVER) /* not 2104{0,1} */
+#define V_CSR8_RXOVER(x) _DD_MAKEVALUE(x,S_CSR8_RXOVER)
+#define G_CSR8_RXOVER(x) _DD_GETVALUE(x,S_CSR8_RXOVER,M_CSR8_RXOVER)
+
+#define M_CSR8_MISSEDWRAP _DD_MAKEMASK1(16)
+#define S_CSR8_MISSED 0
+#define M_CSR8_MISSED _DD_MAKEMASK(16,S_CSR8_MISSED)
+#define V_CSR8_MISSED(x) _DD_MAKEVALUE(x,S_CSR8_MISSED)
+#define G_CSR8_MISSED(x) _DD_GETVALUE(x,S_CSR8_MISSED,M_CSR8_MISSED)
+
+
+/* CSR9: ROM and MII register */
+
+#define S_CSR9_ROMDATA 0
+#define M_CSR9_ROMDATA _DD_MAKEMASK(8,S_CSR9_ROMDATA)
+#define V_CSR9_ROMDATA(x) _DD_MAKEVALUE(x,S_CSR9_ROMDATA)
+#define G_CSR9_ROMDATA(x) _DD_GETVALUE(x,S_CSR9_ROMDATA,M_CSR9_ROMDATA)
+
+#define M_CSR9_SROMCHIPSEL _DD_MAKEMASK1(0) /* not 21040 */
+#define M_CSR9_SROMCLOCK _DD_MAKEMASK1(1) /* not 21040 */
+#define M_CSR9_SROMDATAIN _DD_MAKEMASK1(2) /* not 21040 */
+#define M_CSR9_SROMDATAOUT _DD_MAKEMASK1(3) /* not 21040 */
+
+#define M_CSR9_REGSELECT _DD_MAKEMASK1(10) /* not 21040 */
+#define M_CSR9_SERROMSEL _DD_MAKEMASK1(11) /* not 21040 */
+#define M_CSR9_ROMSEL _DD_MAKEMASK1(12) /* not 21040 */
+#define M_CSR9_ROMWRITE _DD_MAKEMASK1(13) /* not 21040 */
+#define M_CSR9_ROMREAD _DD_MAKEMASK1(14) /* not 21040 */
+#define M_CSR9_MODESEL _DD_MAKEMASK1(15) /* 21041 only */
+#define M_CSR9_MDC _DD_MAKEMASK1(16) /* not 2104{0,1} */
+#define M_CSR9_MDO _DD_MAKEMASK1(17) /* not 2104{0,1} */
+#define M_CSR9_MIIMODE _DD_MAKEMASK1(18) /* not 2104{0,1} */
+#define M_CSR9_MDI _DD_MAKEMASK1(19) /* not 2104{0,1} */
+
+#define M_CSR9_DATANOTVALID _DD_MAKEMASK1(31) /* 21040 only */
+
+#define M_CSR10_BOOTROMADDR _DD_MAKEMASK(18,0) /* not 21040 */
+
+
+/* CSR11 General Purpose Timer register */
+
+#define S_CSR11_GPTIMER 0 /* not 21040 */
+#define M_CSR11_GPTIMER _DD_MAKEMASK(16,S_CSR11_GPTIMER)
+#define V_CSR11_GPTIMER(x) _DD_MAKEVALUE(x,S_CSR11_GPTIMER)
+#define G_CSR11_GPTIMER(x) _DD_GETVALUE(x,S_CSR11_GPTIMER,M_CSR11_GPTIMER)
+
+
+#define M_CSR11_GPTIMERCONT _DD_MAKEMASK1(16) /* not 21040 */
+
+#define S_CSR11_FDAUTOCONF 0 /* 21040 only */
+#define M_CSR11_FDAUTOCONF _DD_MAKEMASK(16,S_CSR11_FDAUTOCONF)
+#define V_CSR11_FDAUTOCONF(x) _DD_MAKEVALUE(x,S_CSR11_FDAUTOCONF)
+#define G_CSR11_FRAUTOCONF(x) _DD_GETVALUE(x,S_CSR11_FDAUTOCONF,M_CSR11_AUTOCONF)
+
+
+/* CSR12: SIA Status register (21143) */
+
+#define M_CSR12_MIIRPA _DD_MAKEMASK1(0)
+#define M_CSR12_100MBLINK _DD_MAKEMASK1(1)
+#define M_CSR12_10MBLINK _DD_MAKEMASK1(2)
+#define M_CSR12_AUTOPOLSTATE _DD_MAKEMASK1(3)
+
+#define M_CSR12_RXAUIACT _DD_MAKEMASK1(8)
+#define M_CSR12_RX10BASETACT _DD_MAKEMASK1(9)
+#define M_CSR12_NLPDETECT _DD_MAKEMASK1(10)
+#define M_CSR12_TXREMFAULT _DD_MAKEMASK1(11)
+
+#define S_CSR12_AUTONEGARBIT 12
+#define M_CSR12_AUTONEGARBIT _DD_MAKEMASK(3,S_CSR12_AUTONEGARBIT)
+#define V_CSR12_AUTONEGARBIT(x) _DD_MAKEVALUE(x,S_CSR12_AUTONEGARBIT)
+#define G_CSR12_AUTONEGARBIT(x) _DD_GETVALUE(x,S_CSR12_AUTONEGARBIT,M_CSR12_AUTONEGARBIT)
+
+#define M_CSR12_LINKPARTNEG _DD_MAKEMASK1(15)
+
+#define S_CSR12_LINKPARTCODE 16
+#define M_CSR12_LINKPARTCODE _DD_MAKEMASK(16,S_CSR12_LINKPARTCODE)
+#define V_CSR12_LINKPARTCODE(x) _DD_MAKEVALUE(x,S_CSR12_LINKPARTCODE)
+#define G_CSR12_LINKPARTCODE(x) _DD_GETVALUE(x,S_CSR12_LINKPARTCODE,M_CSR12_LINKPARTCODE)
+
+
+/* CSR12: SIA Status register (21041, also 31:12, 3:3 as for 21143) */
+
+#define M_CSR12_NETCONNERR _DD_MAKEMASK1(1)
+#define M_CSR12_LINKFAIL _DD_MAKEMASK1(2)
+#define M_CSR12_SELPORTACT _DD_MAKEMASK1(8)
+#define M_CSR12_NONSELPORTACT _DD_MAKEMASK1(9)
+#define M_CSR12_AUTONEGRESTART _DD_MAKEMASK1(10)
+#define M_CSR12_UNSTABLENLP _DD_MAKEMASK1(11)
+
+
+/* CSR12: General Purpose Port register (21140) */
+
+#define S_CSR12_DATA 0
+#define M_CSR12_DATA _DD_MAKEMASK(8,S_CSR12_DATA)
+#define V_CSR12_DATA _DD_MAKEVALUE(x,S_CSR12_DATA,M_CSR12_DATA)
+#define G_CSR12_DATA(x) _DD_GETVALUE(x,S_CSR12_DATA,M_CSR12_DATA)
+
+#define M_CSR12_CONTROL _DD_MAKEMASK1(8)
+
+
+/* CSR13: SIA Mode 0 register (21143 and 21041) */
+
+#define M_CSR13_CONN_NOT_RESET _DD_MAKEMASK1(0)
+#define M_CSR13_CONN_CSR_AUTO _DD_MAKEMAKS1(2) /* 21041 only */
+#define M_CSR13_CONN_AUI_10BT _DD_MAKEMASK1(3)
+
+
+/* CSR14: SIA Mode 1 register (21143 and 21041) */
+
+#define M_CSR14_ENCODER _DD_MAKEMASK1(0)
+#define M_CSR14_LOOPBACK _DD_MAKEMASK1(1)
+#define M_CSR14_DRIVER _DD_MAKEMASK1(2)
+#define M_CSR14_LINKPULSE _DD_MAKEMASK1(3)
+
+#define S_CSR14_COMPENSATE 4
+#define M_CSR14_COMPENSATE _DD_MAKEMASK(2,S_CSR14_COMPENSATE)
+#define V_CSR15_COMPENSATE(x) _DD_MAKEVALUE(x,S_CSR15_COMPENSATE)
+#define G_CSR15_COMPENSATE(x) _DD_GETVALUE(x,S_CSR15_COMPENSATE,M_CSR15_COMPENSATE)
+
+#define M_CSR14_HALFDUPLEX10BASET _DD_MAKEMASK1(6)
+#define M_CSR14_AUTONEGOTIATE _DD_MAKEMASK1(7)
+#define M_CSR14_RXSQUELCH _DD_MAKEMASK1(8)
+#define M_CSR14_COLLSQUELCH _DD_MAKEMASK1(9)
+#define M_CSR14_COLLDETECT _DD_MAKEMASK1(10)
+#define M_CSR14_SIGQUALGEN _DD_MAKEMASK1(11)
+#define M_CSR14_LINKTEST _DD_MAKEMASK1(12)
+#define M_CSR14_AUTOPOLARITY _DD_MAKEMASK1(13)
+#define M_CSR14_SETPOLARITY _DD_MAKEMASK1(14)
+#define M_CSR14_10BASETAUIAUTO _DD_MAKEMASK1(15)
+#define M_CSR14_100BASETHALFDUP _DD_MAKEMASK1(16) /* not 21041 */
+#define M_CSR14_100BASETFULLDUP _DD_MAKEMASK1(17) /* not 21041 */
+#define M_CSR14_100BASET4 _DD_MAKEMASK1(18) /* not 21041 */
+
+#define M_CSR14_10BT_HD 0x7F3F
+#define M_CSR14_10BT_FD 0x7F3D
+
+
+/* CSR15: SIA Mode 2 register (21143 and 21041) */
+
+#define M_CSR15_GP_JABBERDIS _DD_MAKEMASK1(0) /* 21041 only */
+#define M_CSR15_GP_HOSTUNJAB _DD_MAKEMASK1(1)
+#define M_CSR15_GP_JABBERCLK _DD_MAKEMASK1(2)
+#define M_CSR15_GP_AUIBNC _DD_MAKEMASK1(3)
+#define M_CSR15_GP_RXWATCHDIS _DD_MAKEMASK1(4)
+#define M_CSR15_GP_RXWATCHREL _DD_MAKEMASK1(5)
+
+/* (CSR15: 21143 only) */
+
+#define S_CSR15_GP_GPDATA 16
+#define M_CSR15_GP_GPDATA _DD_MAKEMASK(4,S_CSR15_GP_GPDATA)
+#define V_CSR15_GP_GPDATA(x) _DD_MAKEVALUE(x,S_CSR15_GP_GPDATA)
+#define G_CSR15_GP_GPDATA(x) _DD_GETVALUE(x,S_CSR15_GP_GPDATA,M_CSR15_GP_GPDATA)
+
+#define M_CSR15_GP_LED0 _DD_MAKEMASK1(20)
+#define M_CSR15_GP_LED1 _DD_MAKEMASK1(21)
+#define M_CSR15_GP_LED2 _DD_MAKEMASK1(22)
+#define M_CSR15_GP_LED3 _DD_MAKEMASK1(23)
+#define M_CSR15_GP_INTPORT0 _DD_MAKEMASK1(24)
+#define M_CSR15_GP_INTPORT1 _DD_MAKEMASK1(25)
+#define M_CSR15_GP_RXMATCH _DD_MAKEMASK1(26)
+#define M_CSR15_GP_CONTROLWRITE _DD_MAKEMASK1(27)
+#define M_CSR15_GP_GPINT0 _DD_MAKEMASK1(28)
+#define M_CSR15_GP_GPINT1 _DD_MAKEMASK1(29)
+#define M_CSR15_GP_RXMATCHINT _DD_MAKEMASK1(30)
+
+#define M_CSR15_DEFAULT_VALUE 0x00050008
+#define M_CSR15_CONFIG_GEPS_LEDS 0x08af0000
+
+/* (CSR15: 21041 only) */
+
+#define M_CSR15_GP_LED1ENB _DD_MAKEMASK1(6)
+#define M_CSR15_GP_LED1VALUE _DD_MAKEMASK1(7)
+#define M_CSR15_GP_TSTCLK _DD_MAKEMASK1(8)
+#define M_CSR15_GP_FORCEUNSQ _DD_MAKEMASK1(9)
+#define M_CSR15_GP_FORCEFAIL _DD_MAKEMASK1(10)
+#define M_CSR15_GP_LEDSTRDIS _DD_MAKEMASK1(11)
+#define M_CSR15_GP_PLLTEST _DD_MAKEMASK1(12)
+#define M_CSR15_GP_FORCERXLOW _DD_MAKEMASK1(13)
+#define M_CSR15_GP_LED2ENB _DD_MAKEMASK1(14)
+#define M_CSR15_GP_LED2VALUE _DD_MAKEMASK1(15)
+
+
+/* CSR15: Watchdog Timer register (21140) */
+
+#define M_CSR15_WT_JABBER _DD_MAKEMASK1(0)
+#define M_CSR15_WT_HOSTUNJAB _DD_MAKEMASK1(1)
+#define M_CSR15_WT_JABBERCLK _DD_MAKEMASK1(2)
+#define M_CSR15_WT_RXWATCHDIS _DD_MAKEMASK1(4)
+#define M_CSR15_WT_RXWATCHREL _DD_MAKEMASK1(5)
+
+
+/* *********************************************************************
+ * Receive Descriptors
+ ********************************************************************* */
+
+#define M_RDES0_OWNSYS 0
+#define M_RDES0_OWNADAP _DD_MAKEMASK1(31)
+
+#define S_RDES0_FRAMELEN 16
+#define M_RDES0_FRAMELEN _DD_MAKEMASK(14,S_RDES0_FRAMELEN)
+#define V_RDES0_FRAMELEN(x) _DD_MAKEVALUE(x,S_RDES0_FRAMELEN)
+#define G_RDES0_FRAMELEN(x) _DD_GETVALUE(x,S_RDES0_FRAMELEN,M_RDES0_FRAMELEN)
+
+#define M_RDES0_ZERO _DD_MAKEMASK1(0)
+#define M_RDES0_OVFL _DD_MAKEMAKS1(0) /* 21041 only */
+#define M_RDES0_CRCERR _DD_MAKEMASK1(1)
+#define M_RDES0_DRIBBLE _DD_MAKEMASK1(2)
+#define M_RDES0_MIIERROR _DD_MAKEMASK1(3) /* not 21041 */
+#define M_RDES0_WDOGTIMER _DD_MAKEMASK1(4)
+#define M_RDES0_FRAMETYPE _DD_MAKEMASK1(5)
+#define M_RDES0_COLLSEEN _DD_MAKEMASK1(6)
+#define M_RDES0_FRAMETOOLONG _DD_MAKEMASK1(7)
+#define M_RDES0_LASTDES _DD_MAKEMASK1(8)
+#define M_RDES0_FIRSTDES _DD_MAKEMASK1(9)
+#define M_RDES0_MCASTFRAME _DD_MAKEMASK1(10)
+#define M_RDES0_RUNTFRAME _DD_MAKEMASK1(11)
+
+#define S_RDES0_DATATYPE 12
+#define M_RDES0_DATATYPE _DD_MAKEMASK(2,S_RDES0_DATATYPE)
+#define V_RDES0_DATATYPE(x) _DD_MAKEVALUE(x,S_RDES0_DATATYPE)
+#define G_RDES0_DATATYPE(x) _DD_GETVALUE(x,S_RDES0_DATATYPE,M_RDES0_DATATYPE)
+
+#define M_RDES0_ERROR _DD_MAKEMASK1(14)
+#define M_RDES0_ERRORSUM _DD_MAKEMASK1(15)
+#define M_RDES0_FILTFAIL _DD_MAKEMASK1(30) /* not 21041 */
+
+#define S_RDES1_BUF1SIZE 0
+#define M_RDES1_BUF1SIZE _DD_MAKEMASK(11,S_TDES1_BUF1SIZE)
+#define V_RDES1_BUF1SIZE(x) _DD_MAKEVALUE(x,S_RDES1_BUF1SIZE)
+#define G_RDES1_BUF1SIZE(x) _DD_GETVALUE(x,S_RDES1_BUF1SIZE,M_RDES1_BUF1SIZE)
+
+#define S_RDES1_BUF2SIZE 11
+#define M_RDES1_BUF2SIZE _DD_MAKEMASK(11,S_TDES2_BUF2SIZE)
+#define V_RDES1_BUF2SIZE(x) _DD_MAKEVALUE(x,S_RDES1_BUF2SIZE)
+#define G_RDES1_BUF2SIZE(x) _DD_GETVALUE(x,S_RDES1_BUF2SIZE,M_RDES1_BUF2SIZE)
+
+#define M_RDES1_CHAINED _DD_MAKEMASK1(24)
+#define M_RDES1_ENDOFRING _DD_MAKEMASK1(25)
+
+#define M_RDES2_BUFADDR 0xFFFFFFFF
+#define M_RDES3_BUFADDR 0xFFFFFFFF
+
+/* *********************************************************************
+ * Transmit Descriptors
+ ********************************************************************* */
+
+#define M_TDES0_OWNSYS 0
+#define M_TDES0_OWNADAP _DD_MAKEMASK1(31)
+
+#define M_TDES0_DEFERRED _DD_MAKEMASK1(0)
+#define M_TDES0_UNDERFLOW _DD_MAKEMASK1(1)
+#define M_TDES0_LINK_FAIL _DD_MAKEMASK1(2)
+
+#define S_TDES0_COLLCOUNT 3
+#define M_TDES0_COLLCOUNT _DD_MAKEMASK(4,S_TDES0_COLLCOUNT)
+#define V_TDES0_COLLCOUNT(x) _DD_MAKEVALUE(x,S_TDES0_COLLCOUNT)
+#define G_TDES0_COLLCOUNT(x) _DD_GETVALUE(x,S_TDES0_COLLCOUNT,M_TDES0_COLLCOUNT)
+
+#define M_TDES0_HEARTBEAT_FAIL _DD_MAKEMASK1(7)
+#define M_TDES0_EXCESSIVE_COLLISIONS _DD_MAKEMASK1(8)
+#define M_TDES0_LATE_COLLISION _DD_MAKEMASK1(9)
+#define M_TDES0_NO_CARRIER _DD_MAKEMASK1(10)
+#define M_TDES0_LOSS_OF_CARRIER _DD_MAKEMASK1(11)
+#define M_TDES0_TX_JABBER_TIMEOUT _DD_MAKEMASK1(14)
+#define M_TDES0_ERROR_SUMMARY _DD_MAKEMASK1(15)
+#define M_TDES0_OWN_BIT _DD_MAKEMASK1(31)
+
+#define S_TDES1_BUF1SIZE 0
+#define M_TDES1_BUF1SIZE _DD_MAKEMASK(11,S_TDES1_BUF1SIZE)
+#define V_TDES1_BUF1SIZE(x) _DD_MAKEVALUE(x,S_TDES1_BUF1SIZE)
+#define G_TDES1_BUF1SIZE(x) _DD_GETVALUE(x,S_TDES1_BUF1SIZE,M_TDES1_BUF1SIZE)
+
+#define S_TDES1_BUF2SIZE 11
+#define M_TDES1_BUF2SIZE _DD_MAKEMASK(11,S_TDES2_BUF2SIZE)
+#define V_TDES1_BUF2SIZE(x) _DD_MAKEVALUE(x,S_TDES1_BUF2SIZE)
+#define G_TDES1_BUF2SIZE(x) _DD_GETVALUE(x,S_TDES1_BUF2SIZE,M_TDES1_BUF2SIZE)
+
+#define M_TDES1_FT0 _DD_MAKEMASK1(22)
+#define M_TDES1_NOPADDING _DD_MAKEMASK1(23)
+#define M_TDES1_CHAINED _DD_MAKEMASK1(24)
+#define M_TDES1_ENDOFRING _DD_MAKEMASK1(25)
+#define M_TDES1_NOADDCRC _DD_MAKEMASK1(26)
+#define M_TDES1_SETUP _DD_MAKEMASK1(27)
+#define M_TDES1_FT1 _DD_MAKEMASK1(28)
+#define M_TDES1_FIRSTSEG _DD_MAKEMASK1(29)
+#define M_TDES1_LASTSEG _DD_MAKEMASK1(30)
+#define M_TDES1_INTERRUPT _DD_MAKEMASK1(31)
+
+#define M_TDES2_BUFADDR 0xFFFFFFFF
+#define M_TDES3_BUFADDR 0xFFFFFFFF
+
+
+/* CAM */
+
+#define CAM_HASH_THRESHOLD 14
+#define CAM_PERFECT_ENTRIES 16
+
+#define CAM_SETUP_BUFFER_SIZE 192
+
+#endif /* _DC21143_H_ */
diff --git a/cfe/cfe/dev/dev_atapi.c b/cfe/cfe/dev/dev_atapi.c
new file mode 100644
index 0000000..b5f4d9a
--- /dev/null
+++ b/cfe/cfe/dev/dev_atapi.c
@@ -0,0 +1,222 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * ATAPI device driver File: dev_atapi.c
+ *
+ * This is a simple driver for ATAPI devices. The disks
+ * are expected to be connected to the generic bus (this
+ * driver doesn't support PCI).
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "sbmips.h"
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "cfe_timer.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+
+#include "dev_ide_common.h"
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define GETWORD_LE(buf,wordidx) (((unsigned int) (buf)[(wordidx)*2]) + \
+ (((unsigned int) (buf)[(wordidx)*2+1]) << 8))
+
+
+/* *********************************************************************
+ * Forward declarations
+ ********************************************************************* */
+
+extern void _wbflush(void);
+static void atapidrv_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+
+const static cfe_devdisp_t atapidrv_dispatch = {
+ idecommon_open,
+ idecommon_read,
+ idecommon_inpstat,
+ idecommon_write,
+ idecommon_ioctl,
+ idecommon_close,
+ NULL,
+ NULL
+};
+
+const cfe_driver_t atapidrv = {
+ "ATAPI device",
+ "atapi",
+ CFE_DEV_DISK,
+ &atapidrv_dispatch,
+ atapidrv_probe
+};
+
+
+
+/* *********************************************************************
+ * Port I/O routines
+ *
+ * These routines are called back from the common code to do
+ * I/O cycles to the IDE disk. We provide routines for
+ * reading and writing bytes, words, and strings of words.
+ ********************************************************************* */
+
+static uint8_t atapidrv_inb(idecommon_dispatch_t *disp,uint32_t reg)
+{
+ return *((volatile uint8_t *) PHYS_TO_K1(reg+disp->baseaddr));
+}
+
+static uint16_t atapidrv_inw(idecommon_dispatch_t *disp,uint32_t reg)
+{
+ return *((volatile uint16_t *) PHYS_TO_K1((reg+disp->baseaddr)));
+}
+
+static void atapidrv_ins(idecommon_dispatch_t *disp,uint32_t reg,uint8_t *buf,int len)
+{
+ uint16_t data;
+
+ while (len > 0) {
+ data = *((volatile uint16_t *) PHYS_TO_K1(reg+disp->baseaddr));
+
+#ifdef _BYTESWAP_
+ *buf++ = (data >> 8) & 0xFF;
+ *buf++ = (data & 0xFF);
+#else
+ *buf++ = (data & 0xFF);
+ *buf++ = (data >> 8) & 0xFF;
+#endif
+ len--;
+ len--;
+ }
+
+}
+
+static void atapidrv_outb(idecommon_dispatch_t *disp,uint32_t reg,uint8_t val)
+{
+ *((volatile uint8_t *) PHYS_TO_K1(reg+disp->baseaddr)) = val;
+ _wbflush();
+}
+
+static void atapidrv_outw(idecommon_dispatch_t *disp,uint32_t reg,uint16_t val)
+{
+ *((volatile uint16_t *) PHYS_TO_K1(reg+disp->baseaddr)) = val;
+ _wbflush();
+}
+
+static void atapidrv_outs(idecommon_dispatch_t *disp,uint32_t reg,uint8_t *buf,int len)
+{
+ uint16_t data;
+
+ while (len > 0) {
+#ifdef _BYTESWAP_
+ data = (uint16_t) buf[1] + ((uint16_t) buf[0] << 8);
+#else
+ data = (uint16_t) buf[0] + ((uint16_t) buf[1] << 8);
+#endif
+
+ *((volatile uint16_t *) PHYS_TO_K1(reg+disp->baseaddr)) = data;
+ _wbflush();
+
+ buf++;
+ buf++;
+ len--;
+ len--;
+ }
+}
+
+
+
+static void atapidrv_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ idecommon_t *softc;
+ idecommon_dispatch_t *disp;
+ char descr[80];
+ char unitstr[50];
+ int res;
+
+ /*
+ * probe_a is the IDE base address
+ * probe_b is the unit number and other flags
+ * probe_ptr is unused.
+ */
+
+ softc = (idecommon_t *) KMALLOC(sizeof(idecommon_t),0);
+ disp = (idecommon_dispatch_t *) KMALLOC(sizeof(idecommon_dispatch_t),0);
+
+ if (softc && disp) {
+ softc->idecommon_addr = probe_a;
+ softc->idecommon_unit = probe_b;
+
+ disp->ref = softc;
+ disp->baseaddr = softc->idecommon_addr;
+ softc->idecommon_dispatch = disp;
+
+ disp->outb = atapidrv_outb;
+ disp->outw = atapidrv_outw;
+ disp->outs = atapidrv_outs;
+
+ disp->inb = atapidrv_inb;
+ disp->inw = atapidrv_inw;
+ disp->ins = atapidrv_ins;
+
+ res = idecommon_devprobe(softc);
+ if (res < 0) {
+ KFREE(softc);
+ KFREE(disp);
+ return;
+ }
+
+ xsprintf(descr,"%s unit %d at %08X",drv->drv_description,probe_b,probe_a);
+ xsprintf(unitstr,"%d",probe_b);
+ cfe_attach(drv,softc,unitstr,descr);
+ }
+}
+
+
diff --git a/cfe/cfe/dev/dev_bcm1250.c b/cfe/cfe/dev/dev_bcm1250.c
new file mode 100644
index 0000000..8343a46
--- /dev/null
+++ b/cfe/cfe/dev/dev_bcm1250.c
@@ -0,0 +1,275 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * BCM1250 (BCM1250 as PCI device) driver File: dev_bcm1250.c
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "sbmips.h"
+
+#ifndef _SB_MAKE64
+#define _SB_MAKE64(x) ((uint64_t)(x))
+#endif
+#ifndef _SB_MAKEMASK1
+#define _SB_MAKEMASK1(n) (_SB_MAKE64(1) << _SB_MAKE64(n))
+#endif
+
+#include "lib_types.h"
+#include "lib_hssubr.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_error.h"
+#include "cfe_device.h"
+
+#include "pcivar.h"
+#include "pcireg.h"
+
+#include "bsp_config.h"
+
+/* Note that PHYSADDR only works with 32-bit addresses */
+#define PHYSADDR(x) (K0_TO_PHYS((uint32_t)(uintptr_t)(x)))
+
+
+static void bcm1250_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+static int bcm1250_open(cfe_devctx_t *ctx);
+static int bcm1250_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int bcm1250_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int bcm1250_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int bcm1250_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int bcm1250_close(cfe_devctx_t *ctx);
+
+const static cfe_devdisp_t bcm1250_dispatch = {
+ bcm1250_open,
+ bcm1250_read,
+ bcm1250_inpstat,
+ bcm1250_write,
+ bcm1250_ioctl,
+ bcm1250_close,
+ NULL,
+ NULL
+};
+
+const cfe_driver_t bcm1250drv = {
+ "BCM1250",
+ "widget",
+ CFE_DEV_OTHER,
+ &bcm1250_dispatch,
+ bcm1250_probe
+};
+
+
+typedef struct bcm1250_s {
+ uint64_t mailbox;
+ uint64_t mem_base;
+ uint8_t irq; /* interrupt mapping */
+ pcitag_t tag; /* tag for configuration register */
+
+ int downloaded; /* code has already been downloaded. */
+} bcm1250_t;
+
+
+/*
+ * BCM1250_PROBE
+ * probe_a, probe_b and probe_ptr all unused
+ */
+
+static void
+bcm1250_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ int index;
+
+ index = 0;
+ for (;;) {
+ pcitag_t tag;
+
+ if (pci_find_device(0x166d, 0x0001, index, &tag) != 0)
+ break;
+
+ if (tag != 0x00000000) { /* don't configure ourselves */
+ bcm1250_t *softc;
+ char descr[80];
+ phys_addr_t pa;
+
+ softc = (bcm1250_t *) KMALLOC(sizeof(bcm1250_t), 0);
+ if (softc == NULL) {
+ xprintf("BCM1250: No memory to complete probe\n");
+ break;
+ }
+
+ softc->tag = tag;
+
+ pci_map_mem(tag, PCI_MAPREG(0), PCI_MATCH_BYTES, &pa);
+ xsprintf(descr, "%s at 0x%X", drv->drv_description, (uint32_t)pa);
+ softc->mem_base = PHYS_TO_XKSEG_UNCACHED(pa);
+
+ /* Map the CPU0 mailbox registers of the device 1250.
+ Note that our BAR2 space maps to its "alias" mailbox
+ registers. Set bit 3 for mbox_set; clear bit 3 for
+ reading. Address bits 15-4 are don't cares. */
+ pci_map_mem(tag, PCI_MAPREG(2), PCI_MATCH_BYTES, &pa);
+ softc->mailbox = PHYS_TO_XKSEG_UNCACHED(pa);
+
+ softc->downloaded = 0;
+
+ cfe_attach(drv, softc, NULL, descr);
+ }
+ index++;
+ }
+}
+
+
+#include "elf.h"
+
+static int
+elf_header (const uint8_t *hdr)
+{
+ return (hdr[EI_MAG0] == ELFMAG0 &&
+ hdr[EI_MAG1] == ELFMAG1 &&
+ hdr[EI_MAG2] == ELFMAG2 &&
+ hdr[EI_MAG3] == ELFMAG3);
+}
+
+
+#include "cfe_timer.h"
+
+typedef struct {
+ uint32_t addr; /* source address, in device's PCI space */
+ uint32_t len; /* length of this chunk */
+} chunk_desc;
+
+
+#define MBOX_SET_BIT 0x8
+
+extern void download_start(void), download_end(void);
+
+static int
+bcm1250_open(cfe_devctx_t *ctx)
+{
+ bcm1250_t *softc = ctx->dev_softc;
+ uint64_t cmd_p = softc->mailbox + 4;
+
+ if (softc->downloaded) {
+ xprintf("bcm1250_open: Warning: Device previously downloaded\n");
+ softc->downloaded = 0;
+ }
+
+ if (hs_read32(cmd_p) != 0) {
+ xprintf("bcm1250_open: Device not in initial state\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+bcm1250_read(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ return -1;
+}
+
+static int
+bcm1250_inpstat(cfe_devctx_t *ctx, iocb_inpstat_t *inpstat)
+{
+ return -1;
+}
+
+static int
+bcm1250_write(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ bcm1250_t *softc = ctx->dev_softc;
+ uint64_t arg_p = softc->mailbox + 0;
+ uint64_t cmd_p = softc->mailbox + 4;
+ chunk_desc code;
+ uint32_t cmd;
+ int64_t timer;
+ int res;
+
+ /* Note: This code assumes that PHYSADDR gives a PCI memory space
+ address that is accessible via our BAR4 or BAR5 */
+
+ code.addr = PHYSADDR((uint8_t *)buffer->buf_ptr);
+ code.len = buffer->buf_length;
+
+ cmd = 0x1; /* load */
+ if (!elf_header((uint8_t *)buffer->buf_ptr)) {
+ /* No recognizable elf seal, so assume compressed. */
+ cmd |= 0x2;
+ }
+
+ hs_write32(arg_p | MBOX_SET_BIT, PHYSADDR(&code));
+ hs_write32(cmd_p | MBOX_SET_BIT, cmd); /* load */
+
+ /* Wait for handshake */
+
+ res = CFE_ERR_TIMEOUT;
+ TIMER_SET(timer, 5*CFE_HZ);
+ while (!TIMER_EXPIRED(timer)) {
+ if ((hs_read32(cmd_p) & 0x3) == 0) {
+ softc->downloaded = 1;
+ buffer->buf_retlen = 0; /* XXX check this */
+ /* Note that the result code need not be translated only
+ because we are assuming a CFE in the device that is
+ compatible with us. */
+ res = (int)hs_read32(arg_p);
+ break;
+ }
+ POLL();
+ }
+
+ return res;
+}
+
+static int
+bcm1250_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ return -1;
+}
+
+static int
+bcm1250_close(cfe_devctx_t *ctx)
+{
+ return 0;
+}
diff --git a/cfe/cfe/dev/dev_bcm5700.c b/cfe/cfe/dev/dev_bcm5700.c
new file mode 100644
index 0000000..a7bef89
--- /dev/null
+++ b/cfe/cfe/dev/dev_bcm5700.c
@@ -0,0 +1,2557 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * BCM5700/Tigon3 (10/100/1000 EthernetMAC) driver File: dev_bcm5700.c
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "sbmips.h"
+
+#ifndef _SB_MAKE64
+#define _SB_MAKE64(x) ((uint64_t)(x))
+#endif
+#ifndef _SB_MAKEMASK1
+#define _SB_MAKEMASK1(n) (_SB_MAKE64(1) << _SB_MAKE64(n))
+#endif
+
+#include "lib_types.h"
+#include "lib_hssubr.h"
+#include "lib_malloc.h"
+#include "lib_string.h"
+#define blockcopy memcpy
+#include "lib_printf.h"
+#include "lib_queue.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+#include "cfe_timer.h"
+#include "cfe_error.h"
+#include "cfe_irq.h"
+
+#include "pcivar.h"
+#include "pcireg.h"
+
+#include "bcm5700.h"
+#include "mii.h"
+
+/* This is a driver for the Broadcom 570x ("Tigon 3") 10/100/1000 MAC.
+ Currently, only the 5700, 5701 and 5705 have been tested. The 5704
+ dual MAC is not supported, nor is any device with a SerDes PHY.
+
+ Reference:
+ Host Programmer Interface Specification for the BCM570X Family
+ of Highly-Integrated Media Access Controllers, 570X-PG106-R.
+ Broadcom Corp., 16215 Alton Parkway, Irvine CA, 09/27/02
+
+ This BCM1250 version takes advantage of DMA coherence and uses
+ "preserve bit lanes" addresses for all accesses that cross the
+ ZBbus-PCI bridge.
+
+ Note that the 5705 does not fully map all address ranges. Per
+ the manual, reads and writes of the unmapped regions are permitted
+ and do not fault; however, it apparently has some poisoned registers,
+ at least in early revs, that should not be touched. See the
+ conditionals in the code. */
+
+/* PIOSWAP controls whether word-swapping takes place for transactions
+ in which the 570x is the target device. In theory, either value
+ should work (with access macros adjusted as below) and it should be
+ set to be consistent with the settings for 570x as initiator.
+ Empirically, however, some combinations work with the bit clear:
+
+ SWAP=0 SWAP=1
+ 5700 32 PCI OK OK
+ 5700 64 Sturgeon OK OK
+ 5701-32 32 PCI OK OK
+ 5701-32 64 Sturgeon OK OK
+ 5701-32 64 Golem OK OK
+ 5701-64 64 Sturgeon OK OK
+ 5701-64 64 Golem OK FAIL
+ 5705 32 PCI OK OK
+ 5705 64 Sturgeon (OK)* FAIL
+ 5705 64 Golem OK OK
+
+ * PCI status/interrupt ordering problem under load. */
+
+#define PIOSWAP 0
+
+#ifndef T3_DEBUG
+#define T3_DEBUG 0
+#endif
+
+#ifndef T3_BRINGUP
+#define T3_BRINGUP 0
+#endif
+
+/* Broadcom recommends using PHY interrupts instead of autopolling,
+ but I haven't made it work yet. */
+#define T3_AUTOPOLL 1
+
+/* Set IPOLL to drive processing through the pseudo-interrupt
+ dispatcher. Set XPOLL to drive processing by an external polling
+ agent. One must be set; setting both is ok. */
+
+#ifndef IPOLL
+#define IPOLL 0
+#endif
+#ifndef XPOLL
+#define XPOLL 1
+#endif
+
+#define ENET_ADDR_LEN 6 /* size of an ethernet address */
+#define MIN_ETHER_PACK 64 /* min size of a packet */
+#define MAX_ETHER_PACK 1518 /* max size of a packet */
+#define VLAN_TAG_LEN 4 /* VLAN type plus tag */
+#define CRC_SIZE 4 /* size of CRC field */
+
+/* Packet buffers. For the Tigon 3, packet buffer alignment is
+ arbitrary and can be to any byte boundary. We would like it
+ aligned to a cache line boundary for performance, although there is
+ a trade-off with IP/TCP header alignment. */
+
+#define ETH_PKTBUF_LEN (((MAX_ETHER_PACK+31)/32)*32)
+
+#if __long64
+typedef struct eth_pkt_s {
+ queue_t next; /* 16 */
+ uint8_t *buffer; /* 8 */
+ uint32_t flags; /* 4 */
+ int32_t length; /* 4 */
+ uint8_t data[ETH_PKTBUF_LEN];
+} eth_pkt_t;
+#else
+typedef struct eth_pkt_s {
+ queue_t next; /* 8 */
+ uint8_t *buffer; /* 4 */
+ uint32_t flags; /* 4 */
+ int32_t length; /* 4 */
+ uint32_t unused[3]; /* 12 */
+ uint8_t data[ETH_PKTBUF_LEN];
+} eth_pkt_t;
+#endif
+
+#define CACHE_ALIGN 32
+#define ETH_PKTBUF_LINES ((sizeof(eth_pkt_t) + (CACHE_ALIGN-1))/CACHE_ALIGN)
+#define ETH_PKTBUF_SIZE (ETH_PKTBUF_LINES*CACHE_ALIGN)
+#define ETH_PKTBUF_OFFSET (offsetof(eth_pkt_t, data))
+
+#define ETH_PKT_BASE(data) ((eth_pkt_t *)((data) - ETH_PKTBUF_OFFSET))
+
+static void
+show_packet(char c, eth_pkt_t *pkt)
+{
+ int i;
+ int n = (pkt->length < 32 ? pkt->length : 32);
+
+ xprintf("%c[%4d]:", c, pkt->length);
+ for (i = 0; i < n; i++) {
+ if (i % 4 == 0)
+ xprintf(" ");
+ xprintf("%02x", pkt->buffer[i]);
+ }
+ xprintf("\n");
+}
+
+
+static void t3_ether_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+
+/* BCM570X Hardware Common Data Structures
+ XXX These work for 1250 big endian. Need endian testing.
+ XXX Should they move to the header file? */
+
+/* Chip documentation numbers the rings with 1-origin. */
+
+#define RI(n) ((n)-1)
+
+/* BCM570x Ring Sizes (no external memory). Pages 97-98 */
+
+#define TXP_MAX_RINGS 16
+#define TXP_INTERNAL_RINGS 4
+#define TXP_RING_ENTRIES 512
+
+#define RXP_STD_ENTRIES 512
+
+#define RXR_MAX_RINGS 16
+#define RXR_RING_ENTRIES 1024
+
+#define RXR_MAX_RINGS_05 1
+#define RXR_RING_ENTRIES_05 512
+
+
+/* BCM570x Send Buffer Descriptors as a struct. Pages 100-101 */
+
+typedef struct t3_snd_bd_s {
+ uint32_t bufptr_hi;
+ uint32_t bufptr_lo;
+#ifdef __MIPSEB
+ uint16_t length;
+ uint16_t flags;
+ uint16_t pad;
+ uint16_t vlan_tag;
+#elif __MIPSEL
+ uint16_t flags;
+ uint16_t length;
+ uint16_t vlan_tag;
+ uint16_t pad;
+#else
+#error "bcm5700: endian not set"
+#endif
+} t3_snd_bd_t;
+
+#define SND_BD_SIZE 16
+
+#define TX_FLAG_TCP_CKSUM 0x0001
+#define TX_FLAG_IP_CKSUM 0x0002
+#define TX_FLAG_PACKET_END 0x0004
+#define TX_FLAG_IP_FRAG 0x0008
+#define TX_FLAG_IP_FRAG_END 0x0010
+#define TX_FLAG_VLAN_TAG 0x0040
+#define TX_FLAG_COAL_NOW 0x0080
+#define TX_FLAG_CPU_PRE_DMA 0x0100
+#define TX_FLAG_CPU_POST_DMA 0x0200
+#define TX_FLAG_ADD_SRC 0x1000
+#define TX_FLAG_SRC_ADDR_SEL 0x6000
+#define TX_FLAG_NO_CRC 0x8000
+
+/* BCM570x Receive Buffer Descriptors as a struct. Pages 105-107 */
+
+typedef struct t3_rcv_bd_s {
+ uint32_t bufptr_hi;
+ uint32_t bufptr_lo;
+#ifdef __MIPSEB
+ uint16_t index;
+ uint16_t length;
+ uint16_t type;
+ uint16_t flags;
+ uint16_t ip_cksum;
+ uint16_t tcp_cksum;
+ uint16_t error_flag;
+ uint16_t vlan_tag;
+#elif __MIPSEL
+ uint16_t length;
+ uint16_t index;
+ uint16_t flags;
+ uint16_t type;
+ uint16_t tcp_cksum;
+ uint16_t ip_cksum;
+ uint16_t vlan_tag;
+ uint16_t error_flag;
+#else
+#error "bcm5700: endian not set"
+#endif
+ uint32_t pad;
+ uint32_t opaque;
+} t3_rcv_bd_t;
+
+#define RCV_BD_SIZE 32
+
+#define RX_FLAG_PACKET_END 0x0004
+#define RX_FLAG_JUMBO_RING 0x0020
+#define RX_FLAG_VLAN_TAG 0x0040
+#define RX_FLAG_ERROR 0x0400
+#define RX_FLAG_MINI_RING 0x0800
+#define RX_FLAG_IP_CKSUM 0x1000
+#define RX_FLAG_TCP_CKSUM 0x2000
+#define RX_FLAG_IS_TCP 0x4000
+
+#define RX_ERR_BAD_CRC 0x0001
+#define RX_ERR_COLL_DETECT 0x0002
+#define RX_ERR_LINK_LOST 0x0004
+#define RX_ERR_PHY_DECODE 0x0008
+#define RX_ERR_DRIBBLE 0x0010
+#define RX_ERR_MAC_ABORT 0x0020
+#define RX_ERR_SHORT_PKT 0x0040
+#define RX_ERR_TRUNC_NO_RES 0x0080
+#define RX_ERR_GIANT_PKT 0x0100
+
+/* BCM570x Status Block format as a struct (not BCM5705). Pages 110-111. */
+
+typedef struct t3_status_s {
+ uint32_t status;
+ uint32_t tag;
+#ifdef __MIPSEB
+ uint16_t rxc_std_index;
+ uint16_t rxc_jumbo_index;
+ uint16_t reserved2;
+ uint16_t rxc_mini_index;
+ struct {
+ uint16_t send_c;
+ uint16_t return_p;
+ } index [16];
+#elif __MIPSEL
+ uint16_t rxc_jumbo_index;
+ uint16_t rxc_std_index;
+ uint16_t rxc_mini_index;
+ uint16_t reserved2;
+ struct {
+ uint16_t return_p;
+ uint16_t send_c;
+ } index [16];
+#else
+#error "bcm5700: endian not set"
+#endif
+} t3_status_t;
+
+#define M_STATUS_UPDATED 0x00000001
+#define M_STATUS_LINKCHNG 0x00000002
+#define M_STATUS_ERROR 0x00000004
+
+/* BCM570x Statistics Block format as a struct. Pages 112-120 */
+
+typedef struct t3_stats_s {
+ uint64_t stats[L_MAC_STATS/sizeof(uint64_t)];
+} t3_stats_t;
+
+/* End of 570X defined data structures */
+
+
+typedef enum {
+ eth_state_uninit,
+ eth_state_off,
+ eth_state_on,
+} eth_state_t;
+
+typedef struct t3_ether_s {
+ /* status block */
+ volatile t3_status_t *status; /* should be cache-aligned */
+
+ /* PCI access information */
+ uint32_t regbase;
+ uint32_t membase;
+ uint8_t irq;
+ pcitag_t tag; /* tag for configuration registers */
+
+ uint8_t hwaddr[6];
+ uint16_t device; /* chip device code */
+ uint8_t revision; /* chip revision */
+
+ eth_state_t state; /* current state */
+ uint32_t intmask; /* interrupt mask */
+
+ /* packet lists */
+ queue_t freelist;
+ uint8_t *pktpool;
+ queue_t rxqueue;
+
+ /* rings */
+ /* For now, support only the standard Rx Producer Ring */
+ t3_rcv_bd_t *rxp_std; /* Standard Rx Producer Ring */
+ uint32_t rxp_std_index;
+ uint32_t prev_rxp_std_index;
+
+ /* For now, support only 1 priority */
+ uint32_t rxr_entries;
+ t3_rcv_bd_t *rxr_1; /* Rx Return Ring 1 */
+ uint32_t rxr_1_index;
+ t3_snd_bd_t *txp_1; /* Send Ring 1 */
+ uint32_t txp_1_index;
+ uint32_t txc_1_index;
+
+ cfe_devctx_t *devctx;
+
+ /* PHY access */
+ int phy_addr;
+ uint16_t phy_status;
+ uint16_t phy_ability;
+ uint16_t phy_xability;
+
+ /* MII polling control */
+ int phy_change;
+ int mii_polling;
+
+ /* statistics block */
+ t3_stats_t *stats; /* should be cache-aligned */
+
+ /* additional driver statistics */
+ uint32_t rx_interrupts;
+ uint32_t tx_interrupts;
+ uint32_t bogus_interrupts;
+} t3_ether_t;
+
+
+/* Address mapping macros */
+
+#define PTR_TO_PHYS(x) (K0_TO_PHYS((uintptr_t)(x)))
+#define PHYS_TO_PTR(a) ((uint8_t *)PHYS_TO_K0(a))
+
+/* All mappings through the PCI host bridge use match bits mode. */
+#define PHYS_TO_PCI(a) ((uint32_t) (a) | 0x20000000)
+#define PCI_TO_PHYS(a) ((uint32_t) (a) & 0x1FFFFFFF)
+
+#define PCI_TO_PTR(a) (PHYS_TO_PTR(PCI_TO_PHYS(a)))
+#define PTR_TO_PCI(x) (PHYS_TO_PCI(PTR_TO_PHYS(x)))
+
+
+/* Chip access macros */
+
+/* These macros attempt to be compatible with match-bits mode,
+ which may put the data and byte masks into the wrong 32-bit word
+ for 64-bit accesses. See the comment above on PIOSWAP.
+ Externally mastered DMA (control and data) uses match-bits and does
+ specify word-swaps when operating big endian. */
+
+/* Most registers are 32 bits wide and are accessed by 32-bit
+ transactions. The mailbox registers and on-chip RAM are 64-bits
+ wide but are generally accessed by 32-bit transactions.
+ Furthermore, the documentation is ambiguous about which 32-bits of
+ the mailbox is significant. To localize the potential confusions,
+ we define macros for the 3 different cases. */
+
+#if __long64
+#define READCSR(sc,csr) \
+ (*((volatile uint32_t *) \
+ (PHYS_TO_XKSEG_UNCACHED((sc)->regbase+(csr)))))
+
+#define WRITECSR(sc,csr,val) \
+ (*((volatile uint32_t *) \
+ (PHYS_TO_XKSEG_UNCACHED((sc)->regbase+(csr)))) = (val))
+
+#if PIOSWAP
+#define READMBOX(sc,csr) \
+ (*((volatile uint32_t *) \
+ (PHYS_TO_XKSEG_UNCACHED((sc)->regbase+((csr)+4)))))
+
+#define WRITEMBOX(sc,csr,val) \
+ (*((volatile uint32_t *) \
+ (PHYS_TO_XKSEG_UNCACHED((sc)->regbase+((csr)+4)))) = (val))
+
+#define READMEM(sc,csr) \
+ (*((volatile uint32_t *) \
+ (PHYS_TO_XKSEG_UNCACHED((sc)->membase+(csr)))))
+
+#define WRITEMEM(sc,csr,val) \
+ (*((volatile uint32_t *) \
+ (PHYS_TO_XKSEG_UNCACHED((sc)->membase+(csr)))) = (val))
+
+#else
+#define READMBOX(sc,csr) \
+ (*((volatile uint32_t *) \
+ (PHYS_TO_XKSEG_UNCACHED((sc)->regbase+(csr)))))
+
+#define WRITEMBOX(sc,csr,val) \
+ (*((volatile uint32_t *) \
+ (PHYS_TO_XKSEG_UNCACHED((sc)->regbase+(csr)))) = (val))
+
+#define READMEM(sc,csr) \
+ (*((volatile uint32_t *) \
+ (PHYS_TO_XKSEG_UNCACHED((sc)->membase+((csr) ^ 4)))))
+
+#define WRITEMEM(sc,csr,val) \
+ (*((volatile uint32_t *) \
+ (PHYS_TO_XKSEG_UNCACHED((sc)->membase+((csr) ^ 4)))) = (val))
+
+#endif
+#else
+#define READCSR(sc,csr) \
+ (hs_read32(PHYS_TO_XKSEG_UNCACHED((sc)->regbase+(csr))))
+
+#define WRITECSR(sc,csr,val) \
+ (hs_write32(PHYS_TO_XKSEG_UNCACHED((sc)->regbase+(csr), (val))))
+
+#define READMBOX(sc,csr) \
+ (hs_read32(PHYS_TO_XKSEG_UNCACHED((sc)->regbase+(csr)))))
+
+#define WRITEMBOX(sc,csr,val) \
+ (hs_write32(PHYS_TO_XKSEG_UNCACHED((sc)->regbase+(csr)))) = (val))
+
+#define READMEM(sc,csr) \
+ (hs_read32(PHYS_TO_XKSEG_UNCACHED((sc)->membase+(csr))))
+
+#define WRITEMEM(sc,csr,val) \
+ (hs_write32(PHYS_TO_XKSEG_UNCACHED((sc)->membase+(csr), (val))))
+
+#endif
+
+
+/* Entry to and exit from critical sections (currently relative to
+ interrupts only, not SMP) */
+
+#if CFG_INTERRUPTS
+#define CS_ENTER(sc) cfe_disable_irq(sc->irq)
+#define CS_EXIT(sc) cfe_enable_irq(sc->irq)
+#else
+#define CS_ENTER(sc) ((void)0)
+#define CS_EXIT(sc) ((void)0)
+#endif
+
+
+static void
+dumpseq(t3_ether_t *sc, int start, int next)
+{
+ int offset, i, j;
+ int columns = 4;
+ int lines = (((next - start)/4 + 1) + 3)/columns;
+ int step = lines*4;
+
+ offset = start;
+ for (i = 0; i < lines; i++) {
+ xprintf("\nCSR");
+ for (j = 0; j < columns; j++) {
+ if (offset + j*step < next)
+ xprintf(" %04X: %08X ",
+ offset+j*step, READCSR(sc, offset+j*step));
+ }
+ offset += 4;
+ }
+ xprintf("\n");
+}
+
+static void
+dumpcsrs(t3_ether_t *sc, const char *legend)
+{
+ xprintf("%s:\n", legend);
+
+ /* Some device-specific PCI configuration registers */
+ xprintf("-----PCI-----");
+ dumpseq(sc, 0x68, 0x78);
+
+ /* Some general control registers */
+ xprintf("---General---");
+ dumpseq(sc, 0x6800, 0x6810);
+
+ xprintf("-------------\n");
+}
+
+
+/* Packet management */
+
+#define ETH_PKTPOOL_SIZE 64
+#define MIN_RXP_STD_BDS 32
+
+
+static eth_pkt_t *
+eth_alloc_pkt(t3_ether_t *sc)
+{
+ eth_pkt_t *pkt;
+
+ CS_ENTER(sc);
+ pkt = (eth_pkt_t *) q_deqnext(&sc->freelist);
+ CS_EXIT(sc);
+ if (!pkt) return NULL;
+
+ pkt->buffer = pkt->data;
+ pkt->length = ETH_PKTBUF_LEN;
+ pkt->flags = 0;
+
+ return pkt;
+}
+
+
+static void
+eth_free_pkt(t3_ether_t *sc, eth_pkt_t *pkt)
+{
+ CS_ENTER(sc);
+ q_enqueue(&sc->freelist, &pkt->next);
+ CS_EXIT(sc);
+}
+
+static void
+eth_initfreelist(t3_ether_t *sc)
+{
+ int idx;
+ uint8_t *ptr;
+ eth_pkt_t *pkt;
+
+ q_init(&sc->freelist);
+
+ ptr = sc->pktpool;
+ for (idx = 0; idx < ETH_PKTPOOL_SIZE; idx++) {
+ pkt = (eth_pkt_t *) ptr;
+ eth_free_pkt(sc, pkt);
+ ptr += ETH_PKTBUF_SIZE;
+ }
+}
+
+
+/* Utilities */
+
+static const char *
+t3_devname(t3_ether_t *sc)
+{
+ return (sc->devctx != NULL ? cfe_device_name(sc->devctx) : "eth?");
+}
+
+
+/* CRCs */
+
+#define IEEE_CRC32_POLY 0xEDB88320UL /* CRC-32 Poly -- either endian */
+
+uint32_t eth_crc32(const uint8_t *databuf, unsigned int datalen);
+/*static*/ uint32_t
+eth_crc32(const uint8_t *databuf, unsigned int datalen)
+{
+ unsigned int idx, bit, data;
+ uint32_t crc;
+
+ crc = 0xFFFFFFFFUL;
+ for (idx = 0; idx < datalen; idx++)
+ for (data = *databuf++, bit = 0; bit < 8; bit++, data >>= 1)
+ crc = (crc >> 1) ^ (((crc ^ data) & 1) ? IEEE_CRC32_POLY : 0);
+ return crc;
+}
+
+
+/* Descriptor ring management */
+
+static int
+t3_add_rcvbuf(t3_ether_t *sc, eth_pkt_t *pkt)
+{
+ t3_rcv_bd_t *rxp;
+
+ rxp = &(sc->rxp_std[sc->rxp_std_index]);
+ rxp->bufptr_lo = PTR_TO_PCI(pkt->buffer);
+ rxp->length = ETH_PKTBUF_LEN;
+ sc->rxp_std_index++;
+ if (sc->rxp_std_index == RXP_STD_ENTRIES)
+ sc->rxp_std_index = 0;
+ return 0;
+}
+
+static void
+t3_fillrxring(t3_ether_t *sc)
+{
+ eth_pkt_t *pkt;
+ unsigned rxp_ci, rxp_onring;
+
+ rxp_ci = sc->status->rxc_std_index; /* Get a snapshot */
+
+ if (sc->rxp_std_index >= rxp_ci)
+ rxp_onring = sc->rxp_std_index - rxp_ci;
+ else
+ rxp_onring = (sc->rxp_std_index + RXP_STD_ENTRIES) - rxp_ci;
+
+ while (rxp_onring < MIN_RXP_STD_BDS) {
+ pkt = eth_alloc_pkt(sc);
+ if (pkt == NULL) {
+ /* could not allocate a buffer */
+ break;
+ }
+ if (t3_add_rcvbuf(sc, pkt) != 0) {
+ /* could not add buffer to ring */
+ eth_free_pkt(sc, pkt);
+ break;
+ }
+ rxp_onring++;
+ }
+}
+
+static void
+t3_rx_callback(t3_ether_t *sc, eth_pkt_t *pkt)
+{
+ if (T3_DEBUG) show_packet('>', pkt); /* debug */
+
+ CS_ENTER(sc);
+ q_enqueue(&sc->rxqueue, &pkt->next);
+ CS_EXIT(sc);
+}
+
+static void
+t3_procrxring(t3_ether_t *sc)
+{
+ eth_pkt_t *pkt;
+ t3_rcv_bd_t *rxc;
+ volatile t3_status_t *status = sc->status;
+
+ rxc = &(sc->rxr_1[sc->rxr_1_index]);
+ do {
+ pkt = ETH_PKT_BASE(PCI_TO_PTR(rxc->bufptr_lo));
+ pkt->length = rxc->length;
+ if ((rxc->flags & RX_FLAG_ERROR) == 0)
+ t3_rx_callback(sc, pkt);
+ else {
+#if T3_BRINGUP
+ xprintf("%s: rx error %04X\n", t3_devname(sc), rxc->error_flag);
+#endif
+ eth_free_pkt(sc, pkt); /* Could optimize */
+ }
+ sc->rxr_1_index++;
+ rxc++;
+ if (sc->rxr_1_index == sc->rxr_entries) {
+ sc->rxr_1_index = 0;
+ rxc = &(sc->rxr_1[0]);
+ }
+ } while (status->index[RI(1)].return_p != sc->rxr_1_index);
+
+ /* Update the return ring */
+ WRITEMBOX(sc, R_RCV_BD_RTN_CI(1), sc->rxr_1_index);
+
+ /* Refill the producer ring */
+ t3_fillrxring(sc);
+}
+
+
+static int
+t3_transmit(t3_ether_t *sc, eth_pkt_t *pkt)
+{
+ t3_snd_bd_t *txp;
+
+ if (T3_DEBUG) show_packet('<', pkt); /* debug */
+
+ txp = &(sc->txp_1[sc->txp_1_index]);
+ txp->bufptr_hi = 0;
+ txp->bufptr_lo = PTR_TO_PCI(pkt->buffer);
+ txp->length = pkt->length;
+ txp->flags = TX_FLAG_PACKET_END;
+
+ sc->txp_1_index++;
+ if (sc->txp_1_index == TXP_RING_ENTRIES)
+ sc->txp_1_index = 0;
+
+ WRITEMBOX(sc, R_SND_BD_PI(1), sc->txp_1_index);
+
+ return 0;
+}
+
+
+static void
+t3_proctxring(t3_ether_t *sc)
+{
+ eth_pkt_t *pkt;
+ t3_snd_bd_t *txc;
+ volatile t3_status_t *status = sc->status;
+
+ txc = &(sc->txp_1[sc->txc_1_index]);
+ do {
+ pkt = ETH_PKT_BASE(PCI_TO_PTR(txc->bufptr_lo));
+ eth_free_pkt(sc, pkt);
+ sc->txc_1_index++;
+ txc++;
+ if (sc->txc_1_index == TXP_RING_ENTRIES) {
+ sc->txc_1_index = 0;
+ txc = &(sc->txp_1[0]);
+ }
+ } while (status->index[RI(1)].send_c != sc->txc_1_index);
+}
+
+
+static void
+t3_initrings(t3_ether_t *sc)
+{
+ int i;
+ t3_rcv_bd_t *rxp;
+ volatile t3_status_t *status = sc->status;
+
+ /* Clear all Producer BDs */
+ rxp = &(sc->rxp_std[0]);
+ for (i = 0; i < RXP_STD_ENTRIES; i++) {
+ rxp->bufptr_hi = rxp->bufptr_lo = 0;
+ rxp->length = 0;
+ rxp->index = i;
+ rxp->flags = 0;
+ rxp->type = 0;
+ rxp->ip_cksum = rxp->tcp_cksum = 0;
+ rxp++;
+ }
+
+ /* Init the ring pointers */
+
+ sc->rxp_std_index = 0; status->rxc_std_index = 0;
+ sc->rxr_1_index = 0; status->index[RI(1)].return_p = 0;
+ sc->txp_1_index = 0; status->index[RI(1)].send_c = 0;
+
+ /* Allocate some initial buffers for the Producer BD ring */
+ sc->prev_rxp_std_index = 0;
+ t3_fillrxring(sc);
+
+ /* Nothing consumed yet */
+ sc->txc_1_index = 0;
+}
+
+static void
+t3_init(t3_ether_t *sc)
+{
+ /* Allocate buffer pool */
+ sc->pktpool = KMALLOC(ETH_PKTPOOL_SIZE*ETH_PKTBUF_SIZE, CACHE_ALIGN);
+ eth_initfreelist(sc);
+ q_init(&sc->rxqueue);
+
+ t3_initrings(sc);
+}
+
+static void
+t3_reinit(t3_ether_t *sc)
+{
+ eth_initfreelist(sc);
+ q_init(&sc->rxqueue);
+
+ t3_initrings(sc);
+}
+
+
+/* Byte swap utilities. */
+
+#define SWAP4(x) \
+ ((((x) & 0x00FF) << 24) | \
+ (((x) & 0xFF00) << 8) | \
+ (((x) >> 8) & 0xFF00) | \
+ (((x) >> 24) & 0x00FF))
+
+static uint32_t
+swap4(uint32_t x)
+{
+ uint32_t t;
+
+ t = ((x & 0xFF00FF00) >> 8) | ((x & 0x00FF00FF) << 8);
+ return (t >> 16) | ((t & 0xFFFF) << 16);
+}
+
+
+/* EEPROM access functions (BCM5700 and BCM5701 version) */
+
+/* The 570x chips support multiple access methods. We use "Auto Access",
+ which requires that
+ Miscellaneous_Local_Control.Auto_SEEPROM_Access be set,
+ Serial_EEprom.Address.HalfClock be programmed for <= 400 Hz.
+ (both done by initialization code) */
+
+#define EP_MAX_RETRIES 500
+#define EP_DEVICE_ID 0x00 /* default ATMEL device ID */
+
+static void
+eeprom_access_init(t3_ether_t *sc)
+{
+ uint32_t mlctl;
+
+ WRITECSR(sc, R_EEPROM_ADDR, M_EPADDR_RESET | V_EPADDR_HPERIOD(0x60));
+
+ mlctl = READCSR(sc, R_MISC_LOCAL_CTRL);
+ mlctl |= M_MLCTL_EPAUTOACCESS;
+ WRITECSR(sc, R_MISC_LOCAL_CTRL, mlctl);
+}
+
+
+static uint32_t
+eeprom_read_word(t3_ether_t *sc, unsigned int offset)
+{
+ /* Assumes that SEEPROM is already set up for auto access. */
+ uint32_t epaddr, epdata;
+ volatile uint32_t temp;
+ int i;
+
+ epaddr = READCSR(sc, R_EEPROM_ADDR);
+ epaddr &= M_EPADDR_HPERIOD;
+ epaddr |= (V_EPADDR_ADDR(offset) | V_EPADDR_DEVID(EP_DEVICE_ID)
+ | M_EPADDR_RW | M_EPADDR_START | M_EPADDR_COMPLETE);
+ WRITECSR(sc, R_EEPROM_ADDR, epaddr);
+ temp = READCSR(sc, R_EEPROM_ADDR); /* push */
+
+ for (i = 0; i < EP_MAX_RETRIES; i++) {
+ temp = READCSR(sc, R_EEPROM_ADDR);
+ if ((temp & M_EPADDR_COMPLETE) != 0)
+ break;
+ cfe_usleep(10);
+ }
+ if (i == EP_MAX_RETRIES)
+ xprintf("%s: eeprom_read_word: no SEEPROM response @ %x\n",
+ t3_devname(sc), offset);
+
+ epdata = READCSR(sc, R_EEPROM_DATA); /* little endian */
+#ifdef __MIPSEB
+ return swap4(epdata);
+#else
+ return epdata;
+#endif
+}
+
+static int
+eeprom_read_range(t3_ether_t *sc, unsigned int offset, unsigned int len,
+ uint32_t buf[])
+{
+ int index;
+
+ offset &= ~3; len &= ~3; /* 4-byte words only */
+ index = 0;
+
+ while (len > 0) {
+ buf[index++] = eeprom_read_word(sc, offset);
+ offset += 4; len -= 4;
+ }
+
+ return index;
+}
+
+static void
+eeprom_dump_range(const char *label,
+ uint32_t buf[], unsigned int offset, unsigned int len)
+{
+ int index;
+
+ xprintf("EEPROM: %s", label);
+
+ offset &= ~3; len &= ~3; /* 4-byte words only */
+ index = 0;
+
+ for (index = 0; len > 0; index++) {
+ if (index % 8 == 0)
+ xprintf("\n %04x: ", offset);
+ xprintf(" %08x", buf[offset/4]);
+ offset += 4; len -= 4;
+ }
+ xprintf("\n");
+}
+
+
+/* MII access functions. */
+
+/* BCM5401 device specific registers */
+
+#define MII_ISR 0x1A /* Interrupt Status Register */
+#define MII_IMR 0x1B /* Interrupt Mask Register */
+
+#define M_INT_LINKCHNG 0x0002
+
+
+/* The 570x chips support multiple access methods. We use "Auto
+ Access", which requires that MDI_Control_Register.MDI_Select be
+ clear (done by initialization code) */
+
+#define MII_MAX_RETRIES 5000
+
+static void
+mii_access_init(t3_ether_t *sc)
+{
+ WRITECSR(sc, R_MDI_CTRL, 0); /* here for now */
+#if !T3_AUTOPOLL
+ WRITECSR(sc, R_MI_MODE, V_MIMODE_CLKCNT(0x1F)); /* max divider */
+#endif
+}
+
+/* XXX Autopolling should be disabled during reads and writes per the
+ manual, but doing so currently generates recurvise LINKCHNG
+ attentions. */
+
+static uint16_t
+mii_read_register(t3_ether_t *sc, int phy, int index)
+{
+ uint32_t mode;
+ uint32_t comm, val;
+ int i;
+
+ mode = READCSR(sc, R_MI_MODE);
+#if 0 /* for now */
+ if (mode & M_MIMODE_POLLING) {
+ WRITECSR(sc, R_MI_MODE, mode & ~M_MIMODE_POLLING);
+ cfe_usleep(40);
+ }
+#endif
+
+ comm = (V_MICOMM_CMD_RD | V_MICOMM_PHY(phy) | V_MICOMM_REG(index)
+ | M_MICOMM_BUSY);
+ WRITECSR(sc, R_MI_COMM, comm);
+
+ for (i = 0; i < MII_MAX_RETRIES; i++) {
+ val = READCSR(sc, R_MI_COMM);
+ if ((val & M_MICOMM_BUSY) == 0)
+ break;
+ }
+ if (i == MII_MAX_RETRIES)
+ xprintf("%s: mii_read_register: MII always busy\n", t3_devname(sc));
+
+#if 0
+ if (mode & M_MIMODE_POLLING)
+ WRITECSR(sc, R_MI_MODE, mode);
+#endif
+
+ return G_MICOMM_DATA(val);
+}
+
+/* Register reads occasionally return spurious 0's. Verify a zero by
+ doing a second read, or spinning when a zero is "impossible". */
+static uint16_t
+mii_read_register_v(t3_ether_t *sc, int phy, int index, int spin)
+{
+ uint32_t val;
+
+ val = mii_read_register(sc, phy, index);
+ if (val == 0) {
+ do {
+ val = mii_read_register(sc, phy, index);
+ } while (spin && val == 0);
+ }
+ return val;
+}
+
+static void
+mii_write_register(t3_ether_t *sc, int phy, int index, uint16_t value)
+{
+ uint32_t mode;
+ uint32_t comm, val;
+ int i;
+
+ mode = READCSR(sc, R_MI_MODE);
+#if 0 /* for now */
+ if (mode & M_MIMODE_POLLING) {
+ WRITECSR(sc, R_MI_MODE, mode & ~M_MIMODE_POLLING);
+ cfe_usleep(40);
+ }
+#endif
+
+ comm = (V_MICOMM_CMD_WR | V_MICOMM_PHY(phy) | V_MICOMM_REG(index)
+ | V_MICOMM_DATA(value) | M_MICOMM_BUSY);
+ WRITECSR(sc, R_MI_COMM, comm);
+
+ for (i = 0; i < MII_MAX_RETRIES; i++) {
+ val = READCSR(sc, R_MI_COMM);
+ if ((val & M_MICOMM_BUSY) == 0)
+ break;
+ }
+ if (i == MII_MAX_RETRIES)
+ xprintf("%s: mii_write_register: MII always busy\n", t3_devname(sc));
+
+#if 0
+ if (mode & M_MIMODE_POLLING)
+ WRITECSR(sc, R_MI_MODE, mode);
+#endif
+}
+
+static int
+mii_probe(t3_ether_t *sc)
+{
+#if T3_AUTOPOLL /* With autopolling, the code below is not reliable. */
+ return 1; /* Guaranteed for integrated PHYs */
+#else
+ int i;
+ uint16_t id1, id2;
+
+ for (i = 0; i < 32; i++) {
+ id1 = mii_read_register(sc, i, MII_PHYIDR1);
+ id2 = mii_read_register(sc, i, MII_PHYIDR2);
+ if ((id1 != 0x0000 && id1 != 0xFFFF) ||
+ (id2 != 0x0000 && id2 != 0xFFFF)) {
+ if (id1 != id2) return i;
+ }
+ }
+ return -1;
+#endif
+}
+
+#if T3_DEBUG
+#define OUI_BCM 0x001018
+#define IDR_BCM 0x000818
+/* 5400: 4, 5401: 5, 5411: 6, 5421: e, 5701: 11 */
+
+static void
+mii_dump(t3_ether_t *sc, const char *label)
+{
+ int i;
+ uint16_t r;
+ uint32_t idr, part;
+
+ xprintf("%s, MII:\n", label);
+ idr = part = 0;
+
+ /* Required registers */
+ for (i = 0x0; i <= 0x6; ++i) {
+ r = mii_read_register(sc, sc->phy_addr, i);
+ xprintf(" REG%02X: %04X", i, r);
+ if (i == 3 || i == 6)
+ xprintf("\n");
+ if (i == MII_PHYIDR1) {
+ idr |= r << 6;
+ }
+ else if (i == MII_PHYIDR2) {
+ idr |= (r >> 10) & 0x3F;
+ part = (r >> 4) & 0x3F;
+ }
+ }
+
+ /* GMII extensions */
+ for (i = 0x9; i <= 0xA; ++i) {
+ r = mii_read_register(sc, sc->phy_addr, i);
+ xprintf(" REG%02X: %04X", i, r);
+ }
+ r = mii_read_register(sc, sc->phy_addr, 0xF);
+ xprintf(" REG%02X: %04X\n", 0xF, r);
+
+ /* Broadcom extensions (54xx family) */
+ if (idr == IDR_BCM) {
+ for (i = 0x10; i <= 0x14; i++) {
+ r = mii_read_register(sc, sc->phy_addr, i);
+ xprintf(" REG%02X: %04X", i, r);
+ }
+ xprintf("\n");
+ for (i = 0x18; i <= 0x1A; i++) {
+ r = mii_read_register(sc, sc->phy_addr, i);
+ xprintf(" REG%02X: %04X", i, r);
+ }
+ xprintf("\n");
+ }
+}
+#else
+#define mii_dump(sc,label)
+#endif
+
+static void
+mii_enable_interrupts(t3_ether_t *sc)
+{
+ mii_write_register(sc, sc->phy_addr, MII_IMR, ~M_INT_LINKCHNG);
+}
+
+
+/* For 5700/5701, LINKCHNG is read-only in the status register and
+ cleared by writing to CFGCHNG | SYNCCHNG. For the 5705
+ (empirically), LINKCHNG is cleared by writing a one, while CFGCHNG
+ and SYNCCHNG are unimplemented. Thus we can safely clear the
+ interrupt by writing ones to all the above bits. */
+
+#define M_LINKCHNG_CLR \
+ (M_EVT_LINKCHNG | M_MACSTAT_CFGCHNG | M_MACSTAT_SYNCCHNG)
+
+static int
+mii_poll(t3_ether_t *sc)
+{
+ uint32_t macstat;
+ uint16_t status, ability, xability;
+ uint16_t isr;
+
+ macstat = READCSR(sc, R_MAC_STATUS);
+ if ((macstat & (M_EVT_LINKCHNG | M_EVT_MIINT)) != 0)
+ WRITECSR(sc, R_MAC_STATUS, M_LINKCHNG_CLR);
+
+ /* BMSR has read-to-clear bits; read twice. */
+
+ status = mii_read_register(sc, sc->phy_addr, MII_BMSR);
+ status = mii_read_register_v(sc, sc->phy_addr, MII_BMSR, 1);
+ ability = mii_read_register_v(sc, sc->phy_addr, MII_ANLPAR, 0);
+ if (status & BMSR_1000BT_XSR)
+ xability = mii_read_register_v(sc, sc->phy_addr, MII_K1STSR, 0);
+ else
+ xability = 0;
+ isr = mii_read_register(sc, sc->phy_addr, MII_ISR);
+
+ if (status != sc->phy_status
+ || ability != sc->phy_ability || xability != sc->phy_xability) {
+#if T3_DEBUG
+ xprintf("[%04x]", isr);
+ xprintf((macstat & (M_EVT_LINKCHNG | M_EVT_MIINT)) != 0 ? "+" : "-");
+
+ if (status != sc->phy_status)
+ xprintf(" ST: %04x %04x", sc->phy_status, status);
+ if (ability != sc->phy_ability)
+ xprintf(" AB: %04x %04x", sc->phy_ability, ability);
+ if (xability != sc->phy_xability)
+ xprintf(" XA: %04x %04x", sc->phy_xability, xability);
+ xprintf("\n");
+#endif
+ sc->phy_status = status;
+ sc->phy_ability = ability;
+ sc->phy_xability = xability;
+ return 1;
+ }
+ else if ((macstat & (M_EVT_LINKCHNG | M_EVT_MIINT)) != 0) {
+ isr = mii_read_register(sc, sc->phy_addr, MII_ISR);
+ }
+ return 0;
+}
+
+static void
+mii_set_speed(t3_ether_t *sc, int speed)
+{
+ uint16_t control;
+
+ control = mii_read_register(sc, sc->phy_addr, MII_BMCR);
+
+ control &= ~(BMCR_ANENABLE | BMCR_RESTARTAN);
+ mii_write_register(sc, sc->phy_addr, MII_BMCR, control);
+ control &= ~(BMCR_SPEED0 | BMCR_SPEED1 | BMCR_DUPLEX);
+
+ switch (speed) {
+ case ETHER_SPEED_10HDX:
+ default:
+ break;
+ case ETHER_SPEED_10FDX:
+ control |= BMCR_DUPLEX;
+ break;
+ case ETHER_SPEED_100HDX:
+ control |= BMCR_SPEED100;
+ break;
+ case ETHER_SPEED_100FDX:
+ control |= BMCR_SPEED100 | BMCR_DUPLEX ;
+ break;
+ }
+
+ mii_write_register(sc, sc->phy_addr, MII_BMCR, control);
+}
+
+static void
+mii_autonegotiate(t3_ether_t *sc)
+{
+ uint16_t control, status, remote, xremote;
+ unsigned int timeout;
+ int linkspeed;
+ uint32_t mode;
+
+ linkspeed = ETHER_SPEED_UNKNOWN;
+
+ /* Read twice to clear latching bits */
+ status = mii_read_register(sc, sc->phy_addr, MII_BMSR);
+ status = mii_read_register_v(sc, sc->phy_addr, MII_BMSR, 1);
+ mii_dump(sc, "query PHY");
+
+ if ((status & (BMSR_AUTONEG | BMSR_LINKSTAT)) ==
+ (BMSR_AUTONEG | BMSR_LINKSTAT))
+ control = mii_read_register(sc, sc->phy_addr, MII_BMCR);
+ else {
+ for (timeout = 4*CFE_HZ; timeout > 0; timeout -= CFE_HZ/2) {
+ status = mii_read_register(sc, sc->phy_addr, MII_BMSR);
+ if ((status & BMSR_ANCOMPLETE) != 0 || timeout <= 0)
+ break;
+ cfe_sleep(CFE_HZ/2);
+ }
+ }
+
+ remote = mii_read_register_v(sc, sc->phy_addr, MII_ANLPAR, 0);
+
+ /* XXX Empirically, it appears best to set/keep PortMode non-null to
+ get STATUS_LINKCHNG assertions. */
+ mode = READCSR(sc, R_MAC_MODE);
+
+ xprintf("%s: Link speed: ", t3_devname(sc));
+ if ((status & BMSR_ANCOMPLETE) != 0) {
+ /* A link partner was negogiated... */
+
+ if (status & BMSR_1000BT_XSR)
+ xremote = mii_read_register_v(sc, sc->phy_addr, MII_K1STSR, 0);
+ else
+ xremote = 0;
+
+ mode &= ~(M_MACM_PORTMODE | M_MACM_HALFDUPLEX);
+
+ if ((xremote & K1STSR_LP1KFD) != 0) {
+ xprintf("1000BaseT FDX\n");
+ linkspeed = ETHER_SPEED_1000FDX;
+ mode |= V_MACM_PORTMODE(K_MACM_PORTMODE_GMII);
+ }
+ else if ((xremote & K1STSR_LP1KHD) != 0) {
+ xprintf("1000BaseT HDX\n");
+ linkspeed = ETHER_SPEED_1000HDX;
+ mode |= V_MACM_PORTMODE(K_MACM_PORTMODE_GMII) | M_MACM_HALFDUPLEX;
+ }
+ else if ((remote & ANLPAR_TXFD) != 0) {
+ xprintf("100BaseT FDX\n");
+ linkspeed = ETHER_SPEED_100FDX;
+ mode |= V_MACM_PORTMODE(K_MACM_PORTMODE_MII);
+ }
+ else if ((remote & ANLPAR_TXHD) != 0) {
+ xprintf("100BaseT HDX\n");
+ linkspeed = ETHER_SPEED_100HDX;
+ mode |= V_MACM_PORTMODE(K_MACM_PORTMODE_MII) | M_MACM_HALFDUPLEX;
+ }
+ else if ((remote & ANLPAR_10FD) != 0) {
+ xprintf("10BaseT FDX\n");
+ linkspeed = ETHER_SPEED_10FDX;
+ mode |= V_MACM_PORTMODE(K_MACM_PORTMODE_MII);
+ }
+ else if ((remote & ANLPAR_10HD) != 0) {
+ xprintf("10BaseT HDX\n");
+ linkspeed = ETHER_SPEED_10HDX;
+ mode |= V_MACM_PORTMODE(K_MACM_PORTMODE_MII) | M_MACM_HALFDUPLEX;
+ }
+
+ WRITECSR(sc, R_MAC_MODE, mode);
+ }
+ else {
+ /* no link partner convergence */
+ xprintf("Unknown\n");
+ linkspeed = ETHER_SPEED_UNKNOWN;
+ remote = xremote = 0;
+ if (G_MACM_PORTMODE(mode) == K_MACM_PORTMODE_NONE) {
+ /* Keep any previous port mode as the one most likely to reappear.
+ Otherwise, choose one, and 10/100FDX is more likely. */
+ mode |= V_MACM_PORTMODE(K_MACM_PORTMODE_MII);
+ WRITECSR(sc, R_MAC_MODE, mode);
+ }
+ }
+
+ /* clear latching bits, XXX fix flakey reads */
+ status = mii_read_register_v(sc, sc->phy_addr, MII_BMSR, 1);
+ (void)mii_read_register(sc, sc->phy_addr, MII_ISR);
+
+ sc->phy_status = status;
+ sc->phy_ability = remote;
+ sc->phy_xability = xremote;
+
+ mii_dump(sc, "final PHY");
+}
+
+
+static void
+t3_clear(t3_ether_t *sc, unsigned reg, uint32_t mask)
+{
+ uint32_t val;
+ int timeout;
+
+ val = READCSR(sc, reg);
+ val &= ~mask;
+ WRITECSR(sc, reg, val);
+ val = READCSR(sc, reg);
+
+ for (timeout = 4000; (val & mask) != 0 && timeout > 0; timeout -= 100) {
+ cfe_usleep(100);
+ val = READCSR(sc, reg);
+ }
+ if (timeout <= 0)
+ xprintf("%s: cannot clear %04X/%08X\n", t3_devname(sc), reg, mask);
+}
+
+
+/* The following functions collectively implement the recommended
+ BCM5700 Initialization Procedure (Section 8: Device Control) */
+
+static int
+t3_coldreset(t3_ether_t *sc)
+{
+ pcireg_t cmd;
+ pcireg_t bhlc, subsysid;
+ pcireg_t bar0, bar1;
+ pcireg_t cmdx;
+ uint32_t mhc, mcr, mcfg;
+ uint32_t mode;
+ int timeout;
+
+ /* Steps 1-18 */
+ /* Enable memory, also clear R/WC status bits (1) */
+ cmd = pci_conf_read(sc->tag, PCI_COMMAND_STATUS_REG);
+ cmd |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE;
+ pci_conf_write(sc->tag, PCI_COMMAND_STATUS_REG, cmd);
+
+ /* Clear and disable INTA output. (2) */
+ mhc = READCSR(sc, R_MISC_HOST_CTRL);
+ mhc |= M_MHC_MASKPCIINT | M_MHC_CLEARINTA;
+ WRITECSR(sc, R_MISC_HOST_CTRL, mhc);
+
+ /* Save some config registers modified by core clock reset (3). */
+ bhlc = pci_conf_read(sc->tag, PCI_BHLC_REG);
+ subsysid = pci_conf_read(sc->tag, PCI_SUBSYS_ID_REG);
+ /* Empirically, these are clobbered too. */
+ bar0 = pci_conf_read(sc->tag, PCI_MAPREG(0));
+ bar1 = pci_conf_read(sc->tag, PCI_MAPREG(1));
+
+ /* Reset the core clocks (4, 5). */
+ mcfg = READCSR(sc, R_MISC_CFG);
+ mcfg |= M_MCFG_CORERESET;
+ WRITECSR(sc, R_MISC_CFG, mcfg);
+ cfe_usleep(100); /* 100 usec delay */
+
+ /* NB: Until the BARs are restored and reenabled, only PCI
+ configuration reads and writes will succeed. */
+
+ /* Reenable MAC memory (7) */
+ pci_conf_write(sc->tag, PCI_MAPREG(0), bar0);
+ pci_conf_write(sc->tag, PCI_MAPREG(1), bar1);
+ (void)pci_conf_read(sc->tag, PCI_MAPREG(1)); /* push */
+ pci_conf_write(sc->tag, PCI_COMMAND_STATUS_REG, cmd);
+ (void)pci_conf_read(sc->tag, PCI_COMMAND_STATUS_REG); /* push */
+
+ /* Undo some of the resets (6) */
+ mhc = READCSR(sc, R_MISC_HOST_CTRL);
+ mhc |= M_MHC_MASKPCIINT;
+ WRITECSR(sc, R_MISC_HOST_CTRL, mhc);
+
+ /* Verify that core clock resets completed and autocleared. */
+ mcfg = READCSR(sc, R_MISC_CFG);
+ if ((mcfg & M_MCFG_CORERESET) != 0) {
+ xprintf("bcm5700: core clocks stuck in reset\n");
+ }
+
+ /* Configure PCI-X (8) */
+ if (sc->device != K_PCI_ID_BCM5705) {
+ cmdx = pci_conf_read(sc->tag, PCI_PCIX_CMD_REG);
+ cmdx &= ~PCIX_CMD_RLXORDER_ENABLE;
+ pci_conf_write(sc->tag, PCI_PCIX_CMD_REG, cmdx);
+ }
+
+ /* Enable memory arbiter (9) */
+ mode = READCSR(sc, R_MEM_MODE);
+ mode |= M_MAM_ENABLE; /* enable memory arbiter */
+ WRITECSR(sc, R_MEM_MODE, mode);
+
+ /* Assume no external SRAM for now (10) */
+
+ /* Set up MHC for endianness and write enables (11-15) */
+ mhc = READCSR(sc, R_MISC_HOST_CTRL);
+#ifdef __MIPSEL
+ mhc |= M_MHC_ENWORDSWAP; /* XXX check this */
+#endif
+#ifdef __MIPSEB
+ /* Since we use match-bits for Direct PCI access, don't swap bytes. */
+#if PIOSWAP
+ mhc |= M_MHC_ENWORDSWAP;
+#endif
+#endif
+ mhc |= M_MHC_ENINDIRECT | M_MHC_ENPCISTATERW | M_MHC_ENCLKCTRLRW;
+ WRITECSR(sc, R_MISC_HOST_CTRL, mhc);
+
+ /* Set byte swapping (16, 17) */
+ mcr = READCSR(sc, R_MODE_CTRL);
+#ifdef __MIPSEL
+ mcr &= ~M_MCTL_BSWAPDATA;
+ mcr |= M_MCTL_WSWAPCTRL | M_MCTL_WSWAPDATA; /* XXX check this */
+#endif
+#ifdef __MIPSEB
+ mcr &= ~(M_MCTL_BSWAPCTRL | M_MCTL_BSWAPDATA);
+ mcr |= M_MCTL_WSWAPCTRL | M_MCTL_WSWAPDATA;
+#endif
+ WRITECSR(sc, R_MODE_CTRL, mcr);
+
+ /* Disable PXE restart, wait for firmware (18, 19) */
+ if (READMEM(sc, A_PXE_MAILBOX) != T3_MAGIC_NUMBER) {
+ /* Apparently, if the magic number is already set, firmware
+ ignores this attempted handshake. */
+ WRITEMEM(sc, A_PXE_MAILBOX, T3_MAGIC_NUMBER);
+ for (timeout = CFE_HZ; timeout > 0; timeout -= CFE_HZ/10) {
+ if (READMEM(sc, A_PXE_MAILBOX) == ~T3_MAGIC_NUMBER)
+ break;
+ cfe_sleep(CFE_HZ/10);
+ }
+ if (READMEM(sc, A_PXE_MAILBOX) != ~T3_MAGIC_NUMBER)
+ xprintf("bcm5700: no firmware PXE rendevous\n");
+ }
+ else
+ xprintf("bcm5700: PXE magic number already set\n");
+
+ /* Clear Ethernet MAC Mode (20) */
+ WRITECSR(sc, R_MAC_MODE, 0x00000000);
+
+ /* Restore remaining config registers (21) */
+ pci_conf_write(sc->tag, PCI_BHLC_REG, bhlc);
+ pci_conf_write(sc->tag, PCI_SUBSYS_ID_REG, subsysid);
+
+ return 0;
+}
+
+/* XXX Not clear that the following is useful. */
+static int
+t3_warmreset(t3_ether_t *sc)
+{
+ uint32_t mode;
+
+ /* Enable memory arbiter (9) */
+ mode = READCSR(sc, R_MEM_MODE);
+ mode |= M_MAM_ENABLE; /* enable memory arbiter */
+ WRITECSR(sc, R_MEM_MODE, mode);
+
+ /* Clear Ethernet MAC Mode (20) */
+ WRITECSR(sc, R_MAC_MODE, 0x00000000);
+
+ return 0;
+}
+
+
+static int
+t3_init_registers(t3_ether_t *sc)
+{
+ unsigned offset;
+ uint32_t dmac, mcr, mcfg;
+
+ /* Steps 22-29 */
+
+ /* Clear MAC statistics block (22) */
+ for (offset = A_MAC_STATS; offset < A_MAC_STATS+L_MAC_STATS; offset += 4) {
+ WRITEMEM(sc, offset, 0);
+ }
+
+ /* Clear driver status memory region (23) */
+ /* ASSERT (sizeof(t3_status_t) == L_MAC_STATUS) */
+ memset((uint8_t *)sc->status, 0, sizeof(t3_status_t));
+
+ /* Set up PCI DMA control (24) */
+ dmac = READCSR(sc, R_DMA_RW_CTRL);
+ dmac &= ~(M_DMAC_RDCMD | M_DMAC_WRCMD | M_DMAC_MINDMA);
+ dmac |= V_DMAC_RDCMD(K_PCI_MEMRD) | V_DMAC_WRCMD(K_PCI_MEMWR);
+ switch (sc->device) {
+ case K_PCI_ID_BCM5700:
+ case K_PCI_ID_BCM5701:
+ case K_PCI_ID_BCM5702:
+ dmac |= V_DMAC_MINDMA(0xF); /* "Recommended" */
+ break;
+ default:
+ dmac |= V_DMAC_MINDMA(0x0);
+ break;
+ }
+ WRITECSR(sc, R_DMA_RW_CTRL, dmac);
+
+ /* Set DMA byte swapping (25) - XXX repeat of (17) */
+ mcr = READCSR(sc, R_MODE_CTRL);
+#ifdef __MIPSEL
+ mcr &= ~M_MCTL_BSWAPDATA;
+ mcr |= M_MCTL_WSWAPCTRL | M_MCTL_WSWAPDATA; /* XXX check this */
+#endif
+#ifdef __MIPSEB
+ mcr &= ~(M_MCTL_BSWAPCTRL | M_MCTL_BSWAPDATA);
+ mcr |= M_MCTL_WSWAPCTRL | M_MCTL_WSWAPDATA;
+#endif
+ WRITECSR(sc, R_MODE_CTRL, mcr);
+
+ /* Configure host rings (26) */
+ mcr |= M_MCTL_HOSTBDS;
+ WRITECSR(sc, R_MODE_CTRL, mcr);
+
+ /* Indicate driver ready, disable checksums (27, 28) */
+ mcr |= M_MCTL_HOSTUP;
+ mcr |= (M_MCTL_NOTXPHSUM | M_MCTL_NORXPHSUM);
+ WRITECSR(sc, R_MODE_CTRL, mcr);
+
+ /* Configure timer (29) */
+ mcfg = READCSR(sc, R_MISC_CFG);
+ mcfg &= ~M_MCFG_PRESCALER;
+ mcfg |= V_MCFG_PRESCALER(66-1); /* 66 MHz */
+ WRITECSR(sc, R_MISC_CFG, mcfg);
+
+ return 0;
+}
+
+static int
+t3_init_pools(t3_ether_t *sc)
+{
+ uint32_t mode;
+ int timeout;
+
+ /* Steps 30-36. These use "recommended" settings (p 150) */
+
+ /* Configure the MAC memory pool (30) */
+ if (sc->device != K_PCI_ID_BCM5705) {
+ WRITECSR(sc, R_BMGR_MBUF_BASE, A_BUFFER_POOL);
+ WRITECSR(sc, R_BMGR_MBUF_LEN, L_BUFFER_POOL);
+ }
+ else {
+ /* Note: manual appears to recommend not even writing these (?) */
+ /* WRITECSR(sc, R_BMGR_MBUF_BASE, A_RXMBUF); */
+ /* WRITECSR(sc, R_BMGR_MBUF_LEN, 0x8000); */
+ }
+
+ /* Configure the MAC DMA resource pool (31) */
+ WRITECSR(sc, R_BMGR_DMA_BASE, A_DMA_DESCS);
+ WRITECSR(sc, R_BMGR_DMA_LEN, L_DMA_DESCS);
+
+ /* Configure the MAC memory watermarks (32) */
+ WRITECSR(sc, R_BMGR_MBUF_DMA_LOW, 0x50);
+ WRITECSR(sc, R_BMGR_MBUF_RX_LOW, 0x20);
+ WRITECSR(sc, R_BMGR_MBUF_HIGH, 0x60);
+
+ /* Configure the DMA resource watermarks (33) */
+ WRITECSR(sc, R_BMGR_DMA_LOW, 5);
+ WRITECSR(sc, R_BMGR_DMA_HIGH, 10);
+
+ /* Enable the buffer manager (34, 35) */
+ mode = READCSR(sc, R_BMGR_MODE);
+ mode |= (M_BMODE_ENABLE | M_BMODE_MBUFLOWATTN);
+ WRITECSR(sc, R_BMGR_MODE, mode);
+ for (timeout = CFE_HZ/2; timeout > 0; timeout -= CFE_HZ/10) {
+ mode = READCSR(sc, R_BMGR_MODE);
+ if ((mode & M_BMODE_ENABLE) != 0)
+ break;
+ cfe_sleep(CFE_HZ/10);
+ }
+ if ((mode & M_BMODE_ENABLE) == 0)
+ xprintf("bcm5700: buffer manager not enabled\n");
+
+ /* Enable internal queues (36) */
+ WRITECSR(sc, R_FTQ_RESET, 0xFFFFFFFF);
+ (void)READCSR(sc, R_FTQ_RESET); /* push */
+ cfe_sleep(1);
+ WRITECSR(sc, R_FTQ_RESET, 0x00000000);
+
+ return 0;
+}
+
+static int
+t3_init_rings(t3_ether_t *sc)
+{
+ unsigned rcbp;
+ int i;
+
+ /* Steps 37-46 */
+
+ /* Initialize RCBs for Standard Receive Buffer Ring (37) */
+ WRITECSR(sc, R_STD_RCV_BD_RCB+RCB_HOST_ADDR_HIGH, 0);
+ WRITECSR(sc, R_STD_RCV_BD_RCB+RCB_HOST_ADDR_LOW, PTR_TO_PCI(sc->rxp_std));
+ WRITECSR(sc, R_STD_RCV_BD_RCB+RCB_CTRL, V_RCB_MAXLEN(ETH_PKTBUF_LEN));
+ WRITECSR(sc, R_STD_RCV_BD_RCB+RCB_NIC_ADDR, A_STD_RCV_RINGS);
+
+ /* Disable RCBs for Jumbo and Mini Receive Buffer Rings (38,39) */
+ WRITECSR(sc, R_JUMBO_RCV_BD_RCB+RCB_CTRL,
+ RCB_FLAG_USE_EXT_RCV_BD | RCB_FLAG_RING_DISABLED);
+ WRITECSR(sc, R_JUMBO_RCV_BD_RCB+RCB_NIC_ADDR, A_JUMBO_RCV_RINGS);
+ WRITECSR(sc, R_MINI_RCV_BD_RCB+RCB_CTRL, RCB_FLAG_RING_DISABLED);
+ WRITECSR(sc, R_MINI_RCV_BD_RCB+RCB_NIC_ADDR, 0xe000);
+
+ /* Set BD ring replenish thresholds (40) */
+ WRITECSR(sc, R_MINI_RCV_BD_THRESH, 128);
+#if T3_BRINGUP
+ WRITECSR(sc, R_STD_RCV_BD_THRESH, 1);
+#else
+ WRITECSR(sc, R_STD_RCV_BD_THRESH, 25);
+#endif
+ WRITECSR(sc, R_JUMBO_RCV_BD_THRESH, 16);
+
+ /* Disable unused send producer rings 2-16 (41) */
+ for (rcbp = A_SND_RCB(1); rcbp <= A_SND_RCB(16); rcbp += RCB_SIZE)
+ WRITEMEM(sc, rcbp+RCB_CTRL, RCB_FLAG_RING_DISABLED);
+
+ /* Initialize send producer index registers (42) */
+ for (i = 1; i <= TXP_MAX_RINGS; i++) {
+ WRITEMBOX(sc, R_SND_BD_PI(i), 0);
+ WRITEMBOX(sc, R_SND_BD_NIC_PI(i), 0);
+ }
+
+ /* Initialize send producer ring 1 (43) */
+ WRITEMEM(sc, A_SND_RCB(1)+RCB_HOST_ADDR_HIGH, 0);
+ WRITEMEM(sc, A_SND_RCB(1)+RCB_HOST_ADDR_LOW, PTR_TO_PCI(sc->txp_1));
+ WRITEMEM(sc, A_SND_RCB(1)+RCB_CTRL, V_RCB_MAXLEN(TXP_RING_ENTRIES));
+ WRITEMEM(sc, A_SND_RCB(1)+RCB_NIC_ADDR, A_SND_RINGS);
+
+ /* Disable unused receive return rings (44) */
+ for (rcbp = A_RTN_RCB(1); rcbp <= A_RTN_RCB(16); rcbp += RCB_SIZE)
+ WRITEMEM(sc, rcbp+RCB_CTRL, RCB_FLAG_RING_DISABLED);
+
+ /* Initialize receive return ring 1 (45) */
+ WRITEMEM(sc, A_RTN_RCB(1)+RCB_HOST_ADDR_HIGH, 0);
+ WRITEMEM(sc, A_RTN_RCB(1)+RCB_HOST_ADDR_LOW, PTR_TO_PCI(sc->rxr_1));
+ WRITEMEM(sc, A_RTN_RCB(1)+RCB_CTRL, V_RCB_MAXLEN(sc->rxr_entries));
+ WRITEMEM(sc, A_RTN_RCB(1)+RCB_NIC_ADDR, 0x0000);
+
+ /* Initialize receive producer ring mailboxes (46) */
+ WRITEMBOX(sc, R_RCV_BD_STD_PI, 0);
+ WRITEMBOX(sc, R_RCV_BD_JUMBO_PI, 0);
+ WRITEMBOX(sc, R_RCV_BD_MINI_PI, 0);
+
+ return 0;
+}
+
+static int
+t3_configure_mac(t3_ether_t *sc)
+{
+ uint32_t low, high;
+ uint32_t seed;
+ int i;
+
+ /* Steps 47-52 */
+
+ /* Configure the MAC unicast address (47) */
+ high = (sc->hwaddr[0] << 8) | (sc->hwaddr[1]);
+ low = ((sc->hwaddr[2] << 24) | (sc->hwaddr[3] << 16)
+ | (sc->hwaddr[4] << 8) | sc->hwaddr[5]);
+ /* For now, use a single MAC address */
+ WRITECSR(sc, R_MAC_ADDR1_HIGH, high); WRITECSR(sc, R_MAC_ADDR1_LOW, low);
+ WRITECSR(sc, R_MAC_ADDR2_HIGH, high); WRITECSR(sc, R_MAC_ADDR2_LOW, low);
+ WRITECSR(sc, R_MAC_ADDR3_HIGH, high); WRITECSR(sc, R_MAC_ADDR3_LOW, low);
+ WRITECSR(sc, R_MAC_ADDR4_HIGH, high); WRITECSR(sc, R_MAC_ADDR4_LOW, low);
+
+ /* Configure the random backoff seed (48) */
+ seed = 0;
+ for (i = 0; i < 6; i++)
+ seed += sc->hwaddr[i];
+ seed &= 0x3FF;
+ WRITECSR(sc, R_TX_BACKOFF, seed);
+
+ /* Configure the MTU (49) */
+ WRITECSR(sc, R_RX_MTU, MAX_ETHER_PACK+VLAN_TAG_LEN);
+
+ /* Configure the tx IPG (50) */
+ WRITECSR(sc, R_TX_LENS,
+ V_TXLEN_SLOT(0x20) | V_TXLEN_IPG(0x6) | V_TXLEN_IPGCRS(0x2));
+
+ /* Configure the default rx return ring 1 (51) */
+ WRITECSR(sc, R_RX_RULES_CFG, V_RULESCFG_DEFAULT(1));
+
+ /* Configure the receive lists and enable statistics (52) */
+ WRITECSR(sc, R_RCV_LIST_CFG,
+ V_LISTCFG_GROUP(1) | V_LISTCFG_ACTIVE(1) | V_LISTCFG_BAD(1));
+ /* was V_LISTCFG_DEFAULT(1) | V_LISTCFG_ACTIVE(16) | V_LISTCFG_BAD(1) */
+
+ return 0;
+}
+
+static int
+t3_enable_stats(t3_ether_t *sc)
+{
+ uint32_t ctrl;
+
+ /* Steps 53-56 */
+
+ /* Enable rx stats (53,54) */
+ WRITECSR(sc, R_RCV_LIST_STATS_ENB, 0xFFFFFF);
+ ctrl = READCSR(sc, R_RCV_LIST_STATS_CTRL);
+ ctrl |= M_STATS_ENABLE;
+ WRITECSR(sc, R_RCV_LIST_STATS_CTRL, ctrl);
+
+ /* Enable tx stats (55,56) */
+ WRITECSR(sc, R_SND_DATA_STATS_ENB, 0xFFFFFF);
+ ctrl = READCSR(sc, R_SND_DATA_STATS_CTRL);
+ ctrl |= (M_STATS_ENABLE | M_STATS_FASTUPDATE);
+ WRITECSR(sc, R_SND_DATA_STATS_CTRL, ctrl);
+
+ return 0;
+}
+
+static int
+t3_init_coalescing(t3_ether_t *sc)
+{
+ uint32_t mode;
+ int timeout;
+
+ /* Steps 57-68 */
+
+ /* Disable the host coalescing engine (57, 58) */
+ WRITECSR(sc, R_HOST_COAL_MODE, 0);
+ for (timeout = CFE_HZ/2; timeout > 0; timeout -= CFE_HZ/10) {
+ mode = READCSR(sc, R_HOST_COAL_MODE);
+ if (mode == 0)
+ break;
+ cfe_sleep(CFE_HZ/10);
+ }
+ if (mode != 0)
+ xprintf("bcm5700: coalescing engine not disabled\n");
+
+ /* Set coalescing parameters (59-62) */
+#if T3_BRINGUP
+ WRITECSR(sc, R_RCV_COAL_TICKS, 0);
+ WRITECSR(sc, R_RCV_COAL_MAX_CNT, 1);
+#else
+ WRITECSR(sc, R_RCV_COAL_TICKS, 150);
+ WRITECSR(sc, R_RCV_COAL_MAX_CNT, 10);
+#endif
+ WRITECSR(sc, R_RCV_COAL_INT_TICKS, 0);
+ WRITECSR(sc, R_RCV_COAL_INT_CNT, 0);
+#if T3_BRINGUP
+ WRITECSR(sc, R_SND_COAL_TICKS, 0);
+ WRITECSR(sc, R_SND_COAL_MAX_CNT, 1);
+#else
+ WRITECSR(sc, R_SND_COAL_TICKS, 150);
+ WRITECSR(sc, R_SND_COAL_MAX_CNT, 10);
+#endif
+ WRITECSR(sc, R_SND_COAL_INT_TICKS, 0);
+ WRITECSR(sc, R_SND_COAL_INT_CNT, 0);
+
+ /* Initialize host status block address (63) */
+ WRITECSR(sc, R_STATUS_HOST_ADDR, 0);
+ WRITECSR(sc, R_STATUS_HOST_ADDR+4, PTR_TO_PCI(sc->status));
+
+ /* Initialize host statistics block address (64) */
+ WRITECSR(sc, R_STATS_HOST_ADDR, 0);
+ WRITECSR(sc, R_STATS_HOST_ADDR+4, PTR_TO_PCI(sc->stats));
+
+ /* Set statistics block NIC address and tick count (65, 66) */
+ WRITECSR(sc, R_STATS_TICKS, 1000000);
+ WRITECSR(sc, R_STATS_BASE_ADDR, A_MAC_STATS);
+
+ /* Set status block NIC address (67) */
+ WRITECSR(sc, R_STATUS_BASE_ADDR, A_MAC_STATUS);
+
+ /* Enable the host coalescing engine (68) */
+ WRITECSR(sc, R_HOST_COAL_MODE, M_HCM_ENABLE);
+
+ return 0;
+}
+
+static int
+t3_init_dma(t3_ether_t *sc)
+{
+ uint32_t mode;
+
+ /* Steps 69-87 */
+
+ /* Enable receive BD completion, placement, and selector blocks (69-71) */
+ WRITECSR(sc, R_RCV_BD_COMP_MODE, M_MODE_ENABLE | M_MODE_ATTNENABLE);
+ WRITECSR(sc, R_RCV_LIST_MODE, M_MODE_ENABLE);
+ if (sc->device != K_PCI_ID_BCM5705) {
+ WRITECSR(sc, R_RCV_LIST_SEL_MODE, M_MODE_ENABLE | M_MODE_ATTNENABLE);
+ }
+
+ /* Enable DMA engines, enable and clear statistics (72, 73) */
+ mode = READCSR(sc, R_MAC_MODE);
+ mode |= (M_MACM_FHDEENB | M_MACM_RDEENB | M_MACM_TDEENB |
+ M_MACM_RXSTATSENB | M_MACM_RXSTATSCLR |
+ M_MACM_TXSTATSENB | M_MACM_TXSTATSCLR);
+#if T3_AUTOPOLL
+ mode |= V_MACM_PORTMODE(K_MACM_PORTMODE_MII);
+#endif
+
+ WRITECSR(sc, R_MAC_MODE, mode);
+
+#if T3_AUTOPOLL
+ WRITECSR(sc, R_MISC_LOCAL_CTRL, M_MLCTL_INTATTN);
+#endif
+
+ /* Configure GPIOs (74) - skipped */
+
+ /* Clear interrupt mailbox (75) */
+ WRITEMBOX(sc, R_INT_MBOX(0), 0);
+
+ /* Enable DMA completion block (76) */
+ if (sc->device != K_PCI_ID_BCM5705) {
+ WRITECSR(sc, R_DMA_COMP_MODE, M_MODE_ENABLE);
+ }
+
+ /* Configure write and read DMA modes (77, 78) */
+ WRITECSR(sc, R_WR_DMA_MODE, M_MODE_ENABLE | M_ATTN_ALL);
+ WRITECSR(sc, R_RD_DMA_MODE, M_MODE_ENABLE | M_ATTN_ALL);
+
+ return 0;
+}
+
+static int
+t3_init_enable(t3_ether_t *sc)
+{
+ uint32_t mhc;
+ uint32_t pmcs;
+#if T3_AUTOPOLL
+ uint32_t mode, mask;
+#else
+ int i;
+#endif
+
+ /* Steps 79-97 */
+
+ /* Enable completion functional blocks (79-82) */
+ WRITECSR(sc, R_RCV_COMP_MODE, M_MODE_ENABLE | M_MODE_ATTNENABLE);
+ if (sc->device != K_PCI_ID_BCM5705) {
+ WRITECSR(sc, R_MBUF_FREE_MODE, M_MODE_ENABLE);
+ }
+ WRITECSR(sc, R_SND_DATA_COMP_MODE, M_MODE_ENABLE);
+ WRITECSR(sc, R_SND_BD_COMP_MODE, M_MODE_ENABLE | M_MODE_ATTNENABLE);
+
+ /* Enable initiator functional blocks (83-86) */
+ WRITECSR(sc, R_RCV_BD_INIT_MODE, M_MODE_ENABLE | M_MODE_ATTNENABLE);
+ WRITECSR(sc, R_RCV_DATA_INIT_MODE, M_MODE_ENABLE | M_RCVINITMODE_RTNSIZE);
+ WRITECSR(sc, R_SND_DATA_MODE, M_MODE_ENABLE);
+ WRITECSR(sc, R_SND_BD_INIT_MODE, M_MODE_ENABLE | M_MODE_ATTNENABLE);
+
+ /* Enable the send BD selector (87) */
+ WRITECSR(sc, R_SND_BD_SEL_MODE, M_MODE_ENABLE | M_MODE_ATTNENABLE);
+
+ /* Download firmware (88) - skipped */
+
+ /* Enable the MAC (89,90) */
+ WRITECSR(sc, R_TX_MODE, M_MODE_ENABLE); /* optional flow control */
+ WRITECSR(sc, R_RX_MODE, M_MODE_ENABLE); /* other options */
+
+ /* Disable auto-polling (91) */
+ mii_access_init(sc);
+
+ /* Configure power state (92) */
+ pmcs = READCSR(sc, PCI_PMCSR_REG);
+ pmcs &= ~PCI_PMCSR_STATE_MASK;
+ pmcs |= PCI_PMCSR_STATE_D0;
+ WRITECSR(sc, PCI_PMCSR_REG, pmcs);
+
+#if T3_AUTOPOLL
+ /* Program hardware LED control (93) */
+ WRITECSR(sc, R_MAC_LED_CTRL, 0x00); /* LEDs at PHY layer */
+#endif
+
+#if T3_AUTOPOLL
+ /* Ack/clear link change events */
+ WRITECSR(sc, R_MAC_STATUS, M_LINKCHNG_CLR);
+ WRITECSR(sc, R_MI_STATUS, 0);
+
+ /* Enable autopolling */
+ mode = READCSR(sc, R_MI_MODE);
+ mode |= M_MIMODE_POLLING | 0x000c000;
+ WRITECSR(sc, R_MI_MODE, mode);
+
+ /* Enable link state attentions */
+ mask = READCSR(sc, R_MAC_EVENT_ENB);
+ mask |= M_EVT_LINKCHNG;
+ WRITECSR(sc, R_MAC_EVENT_ENB, mask);
+#else
+ /* Initialize link (94) */
+ WRITECSR(sc, R_MI_STATUS, M_MISTAT_LINKED);
+
+ /* Start autonegotiation (95) - see t3_initlink below */
+
+ /* Setup multicast filters (96) */
+ for (i = 0; i < 4; i++)
+ WRITECSR(sc, R_MAC_HASH(i), 0);
+#endif /* T3_AUTOPOLL */
+
+ /* Enable interrupts (97) */
+ mhc = READCSR(sc, R_MISC_HOST_CTRL);
+ mhc &= ~M_MHC_MASKPCIINT;
+ WRITECSR(sc, R_MISC_HOST_CTRL, mhc);
+
+ return 0;
+}
+
+
+static void
+t3_initlink(t3_ether_t *sc)
+{
+ uint32_t mcr;
+
+ sc->phy_addr = mii_probe(sc);
+ if (sc->phy_addr < 0) {
+ xprintf("%s: no PHY found\n", t3_devname(sc));
+ return;
+ }
+#if T3_DEBUG
+ xprintf("%s: PHY addr %d\n", t3_devname(sc), sc->phy_addr);
+#endif
+ if (1) /* XXX Support only autonegotiation for now */
+ mii_autonegotiate(sc);
+ else
+ mii_set_speed(sc, ETHER_SPEED_10HDX);
+
+ mii_enable_interrupts(sc);
+
+ mcr = READCSR(sc, R_MODE_CTRL);
+ mcr |= M_MCTL_MACINT;
+ WRITECSR(sc, R_MODE_CTRL, mcr);
+
+ sc->mii_polling = 0;
+ sc->phy_change = 0;
+}
+
+static void
+t3_shutdownlink(t3_ether_t *sc)
+{
+ uint32_t mcr;
+
+ mcr = READCSR(sc, R_MODE_CTRL);
+ mcr &= ~M_MCTL_MACINT;
+ WRITECSR(sc, R_MODE_CTRL, mcr);
+
+ WRITECSR(sc, R_MAC_EVENT_ENB, 0);
+
+ /* The manual is fuzzy about what to do with the PHY at this
+ point. Empirically, resetting the 5705 PHY (but not others)
+ will cause it to get stuck in 10/100 MII mode. */
+ if (sc->device != K_PCI_ID_BCM5705)
+ mii_write_register(sc, sc->phy_addr, MII_BMCR, BMCR_RESET);
+
+ sc->mii_polling = 0;
+ sc->phy_change = 0;
+}
+
+
+static void
+t3_hwinit(t3_ether_t *sc)
+{
+ if (sc->state != eth_state_on) {
+
+ if (sc->state == eth_state_uninit) {
+ WRITECSR(sc, R_MEMWIN_BASE_ADDR, 0); /* Default memory window */
+ t3_coldreset(sc);
+ }
+ else
+ t3_warmreset(sc);
+
+ t3_init_registers(sc);
+ t3_init_pools(sc);
+ t3_init_rings(sc);
+ t3_configure_mac(sc);
+ t3_enable_stats(sc);
+ t3_init_coalescing(sc);
+ t3_init_dma(sc);
+ t3_init_enable(sc);
+#if T3_DEBUG
+ dumpcsrs(sc, "end init");
+#else
+ (void)dumpcsrs;
+#endif
+
+ eeprom_access_init(sc);
+#if T3_DEBUG
+ {
+ uint32_t eeprom[0x100/4];
+ int i;
+
+ cfe_sleep(1);
+ /* XXX Apparently a few reads can be required to get the
+ AutoAccess logic into a good state. ??? */
+ for (i = 0; i < 4; i++) {
+ eeprom_read_range(sc, 0, 4, eeprom);
+ }
+
+ eeprom_read_range(sc, 0, sizeof(eeprom), eeprom);
+ eeprom_dump_range("Boot Strap", eeprom, 0x00, 20);
+ eeprom_dump_range("Manufacturing Info", eeprom, 0x74, 140);
+ }
+#else
+ (void)eeprom_read_range;
+ (void)eeprom_dump_range;
+#endif
+
+ t3_initlink(sc);
+
+ sc->state = eth_state_off;
+ }
+}
+
+static void
+t3_hwshutdown(t3_ether_t *sc)
+{
+ /* Receive path shutdown */
+ t3_clear(sc, R_RX_MODE, M_MODE_ENABLE);
+ t3_clear(sc, R_RCV_BD_INIT_MODE, M_MODE_ENABLE);
+ t3_clear(sc, R_RCV_LIST_MODE, M_MODE_ENABLE);
+ if (sc->device != K_PCI_ID_BCM5705) {
+ t3_clear(sc, R_RCV_LIST_SEL_MODE, M_MODE_ENABLE);
+ }
+ t3_clear(sc, R_RCV_DATA_INIT_MODE, M_MODE_ENABLE);
+ t3_clear(sc, R_RCV_COMP_MODE, M_MODE_ENABLE);
+ t3_clear(sc, R_RCV_BD_COMP_MODE, M_MODE_ENABLE);
+
+ /* Transmit path shutdown */
+ t3_clear(sc, R_SND_BD_SEL_MODE, M_MODE_ENABLE);
+ t3_clear(sc, R_SND_BD_INIT_MODE, M_MODE_ENABLE);
+ t3_clear(sc, R_SND_DATA_MODE, M_MODE_ENABLE);
+ t3_clear(sc, R_RD_DMA_MODE, M_MODE_ENABLE);
+ t3_clear(sc, R_SND_DATA_COMP_MODE, M_MODE_ENABLE);
+ if (sc->device != K_PCI_ID_BCM5705) {
+ t3_clear(sc, R_DMA_COMP_MODE, M_MODE_ENABLE);
+ }
+ t3_clear(sc, R_SND_BD_COMP_MODE, M_MODE_ENABLE);
+ t3_clear(sc, R_TX_MODE, M_MODE_ENABLE);
+
+ /* Memory shutdown */
+ t3_clear(sc, R_HOST_COAL_MODE, M_HCM_ENABLE);
+ t3_clear(sc, R_WR_DMA_MODE, M_MODE_ENABLE);
+ if (sc->device != K_PCI_ID_BCM5705) {
+ t3_clear(sc, R_MBUF_FREE_MODE, M_MODE_ENABLE);
+ }
+ WRITECSR(sc, R_FTQ_RESET, 0xFFFFFFFF);
+ cfe_sleep(1);
+ WRITECSR(sc, R_FTQ_RESET, 0x00000000);
+ t3_clear(sc, R_BMGR_MODE, M_BMODE_ENABLE);
+ t3_clear(sc, R_MEM_MODE, M_MAM_ENABLE);
+
+ t3_shutdownlink(sc);
+
+ WRITECSR(sc, R_MEMWIN_BASE_ADDR, 0); /* Default memory window */
+ t3_coldreset(sc);
+
+ sc->state = eth_state_uninit;
+}
+
+
+static void
+t3_isr(void *arg)
+{
+ t3_ether_t *sc = (t3_ether_t *)arg;
+ volatile t3_status_t *status = sc->status;
+ uint32_t mac_status;
+ int handled;
+
+ do {
+ WRITEMBOX(sc, R_INT_MBOX(0), 1);
+
+ handled = 0;
+ mac_status = READCSR(sc, R_MAC_STATUS); /* force ordering */
+ status->status &= ~M_STATUS_UPDATED;
+
+ if (status->index[RI(1)].return_p != sc->rxr_1_index) {
+ handled = 1;
+ if (IPOLL) sc->rx_interrupts++;
+ t3_procrxring(sc);
+ }
+
+ if (status->index[RI(1)].send_c != sc->txc_1_index) {
+ handled = 1;
+ if (IPOLL) sc->tx_interrupts++;
+ t3_proctxring(sc);
+ }
+
+ if ((status->status & M_STATUS_LINKCHNG) != 0) {
+ handled = 1;
+#if T3_AUTOPOLL
+ WRITECSR(sc, R_MAC_STATUS, M_LINKCHNG_CLR);
+#endif
+ WRITECSR(sc, R_MAC_STATUS, M_EVT_MICOMPLETE);
+
+ status->status &= ~M_STATUS_LINKCHNG;
+ sc->phy_change = 1;
+ }
+
+ WRITEMBOX(sc, R_INT_MBOX(0), 0);
+ (void)READMBOX(sc, R_INT_MBOX(0)); /* push */
+
+#if (!XPOLL)
+ if (!handled)
+ sc->bogus_interrupts++;
+#endif
+
+ } while ((status->status & M_STATUS_UPDATED) != 0);
+
+ if (sc->rxp_std_index != sc->prev_rxp_std_index) {
+ sc->prev_rxp_std_index = sc->rxp_std_index;
+ WRITEMBOX(sc, R_RCV_BD_STD_PI, sc->rxp_std_index);
+ }
+}
+
+
+static void
+t3_start(t3_ether_t *sc)
+{
+ t3_hwinit(sc);
+
+ sc->intmask = 0;
+
+#if IPOLL
+ cfe_request_irq(sc->irq, t3_isr, sc, CFE_IRQ_FLAGS_SHARED, 0);
+
+#if T3_AUTOPOLL
+ sc->intmask |= M_EVT_LINKCHNG;
+#else
+ sc->intmask |= M_EVT_LINKCHNG | M_EVT_MIINT;
+#endif
+ WRITECSR(sc, R_MAC_EVENT_ENB, sc->intmask);
+#endif
+
+ /* Post some Rcv Producer buffers */
+ sc->prev_rxp_std_index = sc->rxp_std_index;
+ WRITEMBOX(sc, R_RCV_BD_STD_PI, sc->rxp_std_index);
+
+ sc->state = eth_state_on;
+}
+
+static void
+t3_stop(t3_ether_t *sc)
+{
+ WRITECSR(sc, R_MAC_EVENT_ENB, 0);
+ sc->intmask = 0;
+#if IPOLL
+ cfe_free_irq(sc->irq, 0);
+#endif
+
+ if (sc->state == eth_state_on) {
+ sc->state = eth_state_off;
+ t3_hwshutdown(sc);
+ t3_reinit(sc);
+ }
+}
+
+
+static int t3_ether_open(cfe_devctx_t *ctx);
+static int t3_ether_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int t3_ether_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int t3_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int t3_ether_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int t3_ether_close(cfe_devctx_t *ctx);
+static void t3_ether_poll(cfe_devctx_t *ctx, int64_t ticks);
+static void t3_ether_reset(void *softc);
+
+const static cfe_devdisp_t t3_ether_dispatch = {
+ t3_ether_open,
+ t3_ether_read,
+ t3_ether_inpstat,
+ t3_ether_write,
+ t3_ether_ioctl,
+ t3_ether_close,
+ t3_ether_poll,
+ t3_ether_reset
+};
+
+cfe_driver_t bcm5700drv = {
+ "BCM570x Ethernet",
+ "eth",
+ CFE_DEV_NETWORK,
+ &t3_ether_dispatch,
+ t3_ether_probe
+};
+
+
+static void
+t3_delete_sc(t3_ether_t *sc)
+{
+ xprintf("BCM570x attach: No memory to complete probe\n");
+ if (sc != NULL) {
+ if (sc->txp_1 != NULL)
+ KFREE(sc->txp_1);
+ if (sc->rxr_1 != NULL)
+ KFREE(sc->rxr_1);
+ if (sc->rxp_std != NULL)
+ KFREE(sc->rxp_std);
+ if (sc->stats != NULL)
+ KFREE(sc->stats);
+ if (sc->status != NULL)
+ KFREE((t3_ether_t *)sc->status);
+ KFREE(sc);
+ }
+}
+
+static int
+t3_ether_attach(cfe_driver_t *drv, pcitag_t tag, int index)
+{
+ t3_ether_t *sc;
+ char descr[80];
+ phys_addr_t pa;
+ uint32_t base;
+ uint32_t pcictrl;
+ uint32_t addr;
+ pcireg_t device, class;
+ const char *devname;
+ int i;
+
+ pci_map_mem(tag, PCI_MAPREG(0), PCI_MATCH_BITS, &pa);
+ base = (uint32_t)pa;
+
+ sc = (t3_ether_t *) KMALLOC(sizeof(t3_ether_t), 0);
+ if (sc == NULL) {
+ t3_delete_sc(sc);
+ return 0;
+ }
+
+ memset(sc, 0, sizeof(*sc));
+
+ sc->status = NULL;
+ sc->stats = NULL;
+
+ device = pci_conf_read(tag, PCI_ID_REG);
+ class = pci_conf_read(tag, PCI_CLASS_REG);
+ sc->tag = tag;
+ sc->device = PCI_PRODUCT(device);
+ sc->revision = PCI_REVISION(class);
+
+ sc->status = (t3_status_t *) KMALLOC(sizeof(t3_status_t), CACHE_ALIGN);
+ if (sc->status == NULL) {
+ t3_delete_sc(sc);
+ return 0;
+ }
+
+ sc->stats = (t3_stats_t *) KMALLOC(sizeof(t3_stats_t), CACHE_ALIGN);
+ if (sc->stats == NULL) {
+ t3_delete_sc(sc);
+ return 0;
+ }
+
+ if (sc->device == K_PCI_ID_BCM5705)
+ sc->rxr_entries = RXR_RING_ENTRIES_05;
+ else
+ sc->rxr_entries = RXR_RING_ENTRIES;
+
+ sc->rxp_std =
+ (t3_rcv_bd_t *) KMALLOC(RXP_STD_ENTRIES*RCV_BD_SIZE, CACHE_ALIGN);
+ sc->rxr_1 =
+ (t3_rcv_bd_t *) KMALLOC(sc->rxr_entries*RCV_BD_SIZE, CACHE_ALIGN);
+ sc->txp_1 =
+ (t3_snd_bd_t *) KMALLOC(TXP_RING_ENTRIES*SND_BD_SIZE, CACHE_ALIGN);
+ if (sc->rxp_std == NULL || sc->rxr_1 == NULL || sc->txp_1 == NULL) {
+ t3_delete_sc(sc);
+ return 0;
+ }
+
+ sc->regbase = base;
+
+ /* NB: the relative base of memory depends on the access model */
+ pcictrl = pci_conf_read(tag, R_PCI_STATE);
+#if 0 /* XXX This gets spontaneously reset somehow! */
+ if ((pcictrl & M_PCIS_FLATVIEW) != 0)
+ sc->membase = base + 0x01000000; /* Flat mode */
+ else
+#endif
+ sc->membase = base + 0x8000; /* Normal mode: 32K window */
+
+ sc->irq = pci_conf_read(tag, PCI_BPARAM_INTERRUPT_REG) & 0xFF;
+
+ sc->devctx = NULL;
+
+ /* Assume on-chip firmware has initialized the MAC address. */
+ addr = READCSR(sc, R_MAC_ADDR1_HIGH);
+ for (i = 0; i < 2; i++)
+ sc->hwaddr[i] = (addr >> (8*(1-i))) & 0xff;
+ addr = READCSR(sc, R_MAC_ADDR1_LOW);
+ for (i = 0; i < 4; i++)
+ sc->hwaddr[2+i] = (addr >> (8*(3-i))) & 0xff;
+
+ t3_init(sc);
+
+ sc->state = eth_state_uninit;
+
+ switch (sc->device) {
+ case K_PCI_ID_BCM5700:
+ devname = "BCM5700"; break;
+ case K_PCI_ID_BCM5701:
+ devname = "BCM5701"; break;
+ case K_PCI_ID_BCM5702:
+ devname = "BCM5702"; break;
+ case K_PCI_ID_BCM5703:
+ devname = "BCM5703"; break;
+ case K_PCI_ID_BCM5705:
+ devname = "BCM5705"; break;
+ default:
+ devname = "BCM570x"; break;
+ }
+ xsprintf(descr, "%s Ethernet at 0x%X (%02X-%02X-%02X-%02X-%02X-%02X)",
+ devname, sc->regbase,
+ sc->hwaddr[0], sc->hwaddr[1], sc->hwaddr[2],
+ sc->hwaddr[3], sc->hwaddr[4], sc->hwaddr[5]);
+
+ cfe_attach(drv, sc, NULL, descr);
+ return 1;
+}
+
+static void
+t3_ether_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ int index;
+ int n;
+
+ n = 0;
+ index = 0;
+ for (;;) {
+ pcitag_t tag;
+ pcireg_t device;
+
+ if (pci_find_class(PCI_CLASS_NETWORK, index, &tag) != 0)
+ break;
+
+ index++;
+
+ device = pci_conf_read(tag, PCI_ID_REG);
+ if (PCI_VENDOR(device) == K_PCI_VENDOR_BROADCOM) {
+ switch (PCI_PRODUCT(device)) {
+ case K_PCI_ID_BCM5700:
+ case K_PCI_ID_BCM5701:
+ case K_PCI_ID_BCM5702:
+ case K_PCI_ID_BCM5703:
+ case K_PCI_ID_BCM5705:
+ t3_ether_attach(drv, tag, n);
+ n++;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+
+/* The functions below are called via the dispatch vector for the Tigon 3 */
+
+static int
+t3_ether_open(cfe_devctx_t *ctx)
+{
+ t3_ether_t *sc = ctx->dev_softc;
+ t3_stats_t *stats = sc->stats;
+ int i;
+
+ if (sc->state == eth_state_on)
+ t3_stop(sc);
+
+ sc->devctx = ctx;
+
+ sc->rx_interrupts = sc->tx_interrupts = sc->bogus_interrupts = 0;
+ for (i = 0; i < L_MAC_STATS/sizeof(uint64_t); i++)
+ stats->stats[i] = 0;
+
+ t3_start(sc);
+
+ if (XPOLL) t3_isr(sc);
+ return 0;
+}
+
+static int
+t3_ether_read(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ t3_ether_t *sc = ctx->dev_softc;
+ eth_pkt_t *pkt;
+ int blen;
+
+ if (XPOLL) t3_isr(sc);
+
+ if (sc->state != eth_state_on) return -1;
+
+ CS_ENTER(sc);
+ pkt = (eth_pkt_t *) q_deqnext(&(sc->rxqueue));
+ CS_EXIT(sc);
+
+ if (pkt == NULL) {
+ buffer->buf_retlen = 0;
+ return 0;
+ }
+
+ blen = buffer->buf_length;
+ if (blen > pkt->length) blen = pkt->length;
+
+ blockcopy(buffer->buf_ptr, pkt->buffer, blen);
+ buffer->buf_retlen = blen;
+
+ eth_free_pkt(sc, pkt);
+
+ if (XPOLL) t3_isr(sc);
+ return 0;
+}
+
+static int
+t3_ether_inpstat(cfe_devctx_t *ctx, iocb_inpstat_t *inpstat)
+{
+ t3_ether_t *sc = ctx->dev_softc;
+
+ if (XPOLL) t3_isr(sc);
+
+ if (sc->state != eth_state_on) return -1;
+
+ /* We avoid an interlock here because the result is a hint and an
+ interrupt cannot turn a non-empty queue into an empty one. */
+ inpstat->inp_status = (q_isempty(&(sc->rxqueue))) ? 0 : 1;
+
+ return 0;
+}
+
+static int
+t3_ether_write(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ t3_ether_t *sc = ctx->dev_softc;
+ eth_pkt_t *pkt;
+ int blen;
+
+ if (XPOLL) t3_isr(sc);
+
+ if (sc->state != eth_state_on) return -1;
+
+ pkt = eth_alloc_pkt(sc);
+ if (!pkt) return CFE_ERR_NOMEM;
+
+ blen = buffer->buf_length;
+ if (blen > pkt->length) blen = pkt->length;
+
+ blockcopy(pkt->buffer, buffer->buf_ptr, blen);
+ pkt->length = blen;
+
+ if (t3_transmit(sc, pkt) != 0) {
+ eth_free_pkt(sc,pkt);
+ return CFE_ERR_IOERR;
+ }
+
+ if (XPOLL) t3_isr(sc);
+ return 0;
+}
+
+static int
+t3_ether_ioctl(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ t3_ether_t *sc = ctx->dev_softc;
+
+ switch ((int)buffer->buf_ioctlcmd) {
+ case IOCTL_ETHER_GETHWADDR:
+ memcpy(buffer->buf_ptr, sc->hwaddr, sizeof(sc->hwaddr));
+ return 0;
+
+ default:
+ return -1;
+ }
+}
+
+static int
+t3_ether_close(cfe_devctx_t *ctx)
+{
+ t3_ether_t *sc = ctx->dev_softc;
+ t3_stats_t *stats = sc->stats;
+ uint32_t inpkts, outpkts, interrupts;
+ int i;
+
+ t3_stop(sc);
+
+#if T3_BRINGUP
+ for (i = 0; i < L_MAC_STATS/sizeof(uint64_t); i++) {
+ if (stats->stats[i] != 0)
+ xprintf(" stats[%d] = %8lld\n", i, stats->stats[i]);
+ }
+#else
+ (void) i;
+#endif
+
+ inpkts = stats->stats[ifHCInUcastPkts]
+ + stats->stats[ifHCInMulticastPkts]
+ + stats->stats[ifHCInBroadcastPkts];
+ outpkts = stats->stats[ifHCOutUcastPkts]
+ + stats->stats[ifHCOutMulticastPkts]
+ + stats->stats[ifHCOutBroadcastPkts];
+ interrupts = stats->stats[nicInterrupts];
+
+ /* Empirically, counters on the 5705 are always zero. */
+ if (sc->device != K_PCI_ID_BCM5705) {
+ xprintf("%s: %d sent, %d received, %d interrupts\n",
+ t3_devname(sc), outpkts, inpkts, interrupts);
+ if (IPOLL) {
+ xprintf(" %d rx interrupts, %d tx interrupts",
+ sc->rx_interrupts, sc->tx_interrupts);
+ if (sc->bogus_interrupts != 0)
+ xprintf(", %d bogus interrupts", sc->bogus_interrupts);
+ xprintf("\n");
+ }
+ }
+
+ sc->devctx = NULL;
+ return 0;
+}
+
+static void
+t3_ether_poll(cfe_devctx_t *ctx, int64_t ticks)
+{
+ t3_ether_t *sc = ctx->dev_softc;
+ int changed;
+
+ if (sc->phy_change && sc->state != eth_state_uninit && !sc->mii_polling) {
+ uint32_t mask;
+
+ sc->mii_polling++;
+ mask = READCSR(sc, R_MAC_EVENT_ENB);
+ WRITECSR(sc, R_MAC_EVENT_ENB, 0);
+
+ changed = mii_poll(sc);
+ if (changed) {
+ mii_autonegotiate(sc);
+ }
+ sc->phy_change = 0;
+ sc->mii_polling--;
+
+ WRITECSR(sc, R_MAC_EVENT_ENB, mask);
+ }
+}
+
+static void
+t3_ether_reset(void *softc)
+{
+ t3_ether_t *sc = (t3_ether_t *)softc;
+
+ /* Turn off the Ethernet interface. */
+
+ if (sc->state == eth_state_on)
+ t3_stop(sc);
+
+ sc->state = eth_state_uninit;
+}
diff --git a/cfe/cfe/dev/dev_bcm5821.c b/cfe/cfe/dev/dev_bcm5821.c
new file mode 100644
index 0000000..3dede0f
--- /dev/null
+++ b/cfe/cfe/dev/dev_bcm5821.c
@@ -0,0 +1,1592 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * BC5821 crypto accelerator driver File: dev_bcm5821.c
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+/*
+ CFE Driver plus test programs for the BCM5820 and BCM5821 crypto
+ coprocessor chips.
+ Reference:
+ BCM5821 Super-eCommerce Processor
+ Data Sheet 5821-DS105-D1 (draft, 7/26/02)
+ Broadcom Corp., 16215 Alton Parkway, Irvine, CA.
+*/
+
+/* The performance counter usage assumes a BCM11xx or BCM1250 part */
+#ifndef _SB14XX_
+
+#include "sbmips.h"
+#include "sb1250_defs.h"
+#include "sb1250_regs.h"
+
+#ifndef _SB_MAKE64
+#define _SB_MAKE64(x) ((uint64_t)(x))
+#endif
+#ifndef _SB_MAKEMASK1
+#define _SB_MAKEMASK1(n) (_SB_MAKE64(1) << _SB_MAKE64(n))
+#endif
+
+#include "lib_types.h"
+#include "lib_hssubr.h"
+#include "lib_malloc.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+#include "lib_queue.h"
+
+#include "addrspace.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_timer.h"
+#include "cfe_devfuncs.h"
+#include "cfe_irq.h"
+
+#include "pcivar.h"
+#include "pcireg.h"
+
+#include "bcm5821.h"
+
+/* The version that works by polling the CPU's Cause register doesn't
+ do handshakes or checks to detect merged interrupts. It currently
+ works when the 5821 is on the direct PCI bus but can behave
+ erratically when the 5821 is behind an LDT-to-PCI bridge that does
+ interrupt mapping and relies on EOI. */
+
+extern int32_t _getcause(void); /* return value of CP0 CAUSE */
+
+#define IMR_POINTER(cpu,reg) \
+ ((volatile uint64_t *)(PHYS_TO_K1(A_IMR_REGISTER(cpu,reg))))
+
+#define CACHE_LINE_SIZE 32
+
+static void bcm5821_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+typedef struct bcm5821_state_s {
+ uint32_t regbase;
+ uint8_t irq;
+ pcitag_t tag; /* tag for configuration registers */
+
+ uint16_t device; /* chip device code */
+ uint8_t revision; /* chip revision */
+
+} bcm5821_state_t;
+
+
+/* Address mapping macros */
+
+/* Note that PTR_TO_PHYS only works with 32-bit addresses, but then
+ so does the bcm528x. */
+#define PTR_TO_PHYS(x) (K0_TO_PHYS((uintptr_t)(x)))
+#define PHYS_TO_PTR(a) ((void *)PHYS_TO_K0(a))
+
+/* For the 5821, all mappings through the PCI host bridge use match
+ bits mode. This works because the NORM_PCI bit in DMA Control is
+ clear. The 5820 does not have such a bit, so pointers to data byte
+ sequences use match bytes, but control blocks use match bits. */
+#define PHYS_TO_PCI(a) ((uint32_t) (a) | 0x20000000)
+#define PHYS_TO_PCI_D(a) (a)
+#define PCI_TO_PHYS(a) ((uint32_t) (a) & 0x1FFFFFFF)
+
+#if __long64
+#define READCSR(sc,csr) \
+ (*((volatile uint32_t *) \
+ (PHYS_TO_XKSEG_UNCACHED((sc)->regbase+(csr)))))
+
+#define WRITECSR(sc,csr,val) \
+ (*((volatile uint32_t *) \
+ (PHYS_TO_XKSEG_UNCACHED((sc)->regbase+(csr)))) = (val))
+#else
+#define READCSR(sc,csr) \
+ (hs_read32(PHYS_TO_XKSEG_UNCACHED((sc)->regbase+(csr))))
+
+#define WRITECSR(sc,csr,val) \
+ (hs_write32(PHYS_TO_XKSEG_UNCACHED((sc)->regbase+(csr)), (val)))
+#endif
+
+static void
+dumpcsrs(bcm5821_state_t *sc, const char *legend)
+{
+ xprintf("%s:\n", legend);
+ xprintf("---DMA---\n");
+ /* DMA control and status registers */
+ xprintf("MCR1: %08X CTRL: %08X STAT: %08X ERR: %08X\n",
+ READCSR(sc, R_MCR1), READCSR(sc, R_DMA_CTRL),
+ READCSR(sc, R_DMA_STAT), READCSR(sc, R_DMA_ERR));
+ xprintf("MCR2: %08X\n", READCSR(sc, R_MCR2));
+ xprintf("-------------\n");
+}
+
+
+static void
+bcm5821_init(bcm5821_state_t *sc)
+{
+}
+
+static void
+bcm5821_hwinit(bcm5821_state_t *sc)
+{
+ uint32_t ctrl;
+ uint32_t status;
+
+ ctrl = (M_DMA_CTRL_MCR1_INT_EN | M_DMA_CTRL_MCR2_INT_EN |
+ M_DMA_CTRL_DMAERR_EN);
+ if (sc->device == K_PCI_ID_BCM5820)
+ ctrl |= (M_DMA_CTRL_NORM_PCI | M_DMA_CTRL_LE_CRYPTO);
+ /* Note for 5821: M_DMA_CTRL_NORM_PCI, M_DMA_CTRL_LE_CRYPTO not set. */
+#if 0 /* Empirically, this reduces performance. */
+ if (sc->device != K_PCI_ID_BCM5820)
+ ctrl |= M_DMA_CTRL_WR_BURST;
+#endif
+ WRITECSR(sc, R_DMA_CTRL, ctrl);
+
+ status = READCSR(sc, R_DMA_STAT);
+ WRITECSR(sc, R_DMA_STAT, status); /* reset write-to-clear bits */
+ status = READCSR(sc, R_DMA_STAT);
+
+ dumpcsrs(sc, "init");
+}
+
+
+static void
+bcm5821_start(bcm5821_state_t *sc)
+{
+ bcm5821_hwinit(sc);
+}
+
+static void
+bcm5821_stop(bcm5821_state_t *sc)
+{
+ WRITECSR(sc, R_DMA_CTRL, 0);
+}
+
+
+static int bcm5821_open(cfe_devctx_t *ctx);
+static int bcm5821_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int bcm5821_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int bcm5821_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int bcm5821_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int bcm5821_close(cfe_devctx_t *ctx);
+
+const static cfe_devdisp_t bcm5821_dispatch = {
+ bcm5821_open,
+ bcm5821_read,
+ bcm5821_inpstat,
+ bcm5821_write,
+ bcm5821_ioctl,
+ bcm5821_close,
+ NULL,
+ NULL
+};
+
+cfe_driver_t bcm5821drv = {
+ "BCM582x crypto",
+ "crypt",
+ CFE_DEV_OTHER,
+ &bcm5821_dispatch,
+ bcm5821_probe
+};
+
+
+static int
+bcm5821_attach(cfe_driver_t *drv, pcitag_t tag, int index)
+{
+ bcm5821_state_t *sc;
+ char descr[80];
+ phys_addr_t pa;
+ uint32_t base;
+ pcireg_t device, class;
+
+ pci_map_mem(tag, PCI_MAPREG(0), PCI_MATCH_BITS, &pa);
+ base = (uint32_t)pa;
+
+ sc = (bcm5821_state_t *) KMALLOC(sizeof(bcm5821_state_t),0);
+ if (sc == NULL) {
+ xprintf("BCM5821: No memory to complete probe\n");
+ return 0;
+ }
+
+ memset(sc, 0, sizeof(*sc));
+
+ sc->regbase = base;
+
+ sc->irq = pci_conf_read(tag, PCI_BPARAM_INTERRUPT_REG) & 0xFF;
+
+ device = pci_conf_read(tag, PCI_ID_REG);
+ class = pci_conf_read(tag, PCI_CLASS_REG);
+
+ sc->tag = tag;
+ sc->device = PCI_PRODUCT(device);
+ sc->revision = PCI_REVISION(class);
+
+ bcm5821_init(sc);
+
+ xsprintf(descr, "BCM%04X Crypto at 0x%08X", sc->device, base);
+ cfe_attach(drv, sc, NULL, descr);
+
+ return 1;
+}
+
+static void
+bcm5821_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ int index;
+ int n;
+
+ n = 0;
+ index = 0;
+ for (;;) {
+ pcitag_t tag;
+ pcireg_t device;
+
+ if (pci_find_class(PCI_CLASS_PROCESSOR, index, &tag) != 0)
+ break;
+
+ index++;
+
+ device = pci_conf_read(tag, PCI_ID_REG);
+ if (PCI_VENDOR(device) == K_PCI_VENDOR_BROADCOM) {
+ if (PCI_PRODUCT(device) == K_PCI_ID_BCM5820 ||
+ PCI_PRODUCT(device) == K_PCI_ID_BCM5821) {
+ bcm5821_attach(drv, tag, n);
+ n++;
+ }
+ }
+ }
+}
+
+
+/* The functions below are called via the dispatch vector for the 5821 */
+
+static int
+bcm5821_open(cfe_devctx_t *ctx)
+{
+ bcm5821_state_t *sc = ctx->dev_softc;
+
+ bcm5821_start(sc);
+ return 0;
+}
+
+static int
+bcm5821_read(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ return -1;
+}
+
+static int
+bcm5821_inpstat(cfe_devctx_t *ctx, iocb_inpstat_t *inpstat)
+{
+ return 0;
+}
+
+static int
+bcm5821_write(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ return -1;
+}
+
+static int
+bcm5821_ioctl(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ return -1;
+}
+
+static int
+bcm5821_close(cfe_devctx_t *ctx)
+{
+ bcm5821_state_t *sc = ctx->dev_softc;
+
+ bcm5821_stop(sc);
+ return 0;
+}
+
+
+/* Additional hooks for testing. */
+
+static int
+bcm5821_dump_cc1 (uint32_t *cc)
+{
+ int i;
+ unsigned op = G_CC_OPCODE(cc[0]);
+ unsigned cc_words = G_CC_LEN(cc[0])/4;
+ int chain_out; /* Whether the output is chained or fixed */
+
+ chain_out = 1; /* default */
+
+ switch (op) {
+
+ case K_SSL_MAC:
+ xprintf("(SSL_MAC)\n");
+ for (i = 0; i < SSL_MAC_CMD_WORDS; i++)
+ xprintf(" %2d: %08x\n", i, cc[i]);
+ chain_out = 0;
+ break;
+
+ case K_ARC4:
+ xprintf("(ARCFOUR)\n");
+ for (i = 0; i < 3; i++)
+ xprintf(" %2d: %08x\n", i, cc[i]);
+ for (i = 0; i < 256/4; i += 4)
+ xprintf(" %2d: %08x %08x %08x %08x\n",
+ i+3, cc[i+3], cc[i+4], cc[i+5], cc[i+6]);
+ break;
+
+ case K_HASH:
+ xprintf("(HASH)\n");
+ for (i = 0; i < 2; i++)
+ xprintf(" %2d: %08x\n", i, cc[i]);
+ chain_out = 0;
+ break;
+
+ case K_TLS_HMAC:
+ chain_out = 0;
+ /* fall through */
+
+ default: /* NYI: K_IPSEC_3DES (5821 only), K_SSL_3DES */
+ xprintf("\n");
+ for (i = 0; i < cc_words; i++)
+ xprintf(" %2d: %08x\n", i, cc[i]);
+ break;
+ }
+
+ return chain_out;
+}
+
+static int
+bcm5821_dump_cc2 (uint32_t *cc)
+{
+ int i;
+ unsigned op = G_CC_OPCODE(cc[0]);
+ unsigned cc_words = G_CC_LEN(cc[0])/4;
+ int chain_out; /* Whether the output is chained or fixed */
+
+ chain_out = 1; /* default */
+
+ switch (op) {
+
+ case K_RNG_DIRECT:
+ xprintf(" RNG_DIRECT\n");
+ chain_out = 0;
+ for (i = 0; i < 1; i++)
+ xprintf(" %2d: %08x\n", i, cc[i]);
+ break;
+
+ case K_RNG_SHA1:
+ xprintf(" RNG_SHA1\n");
+ chain_out = 0;
+ for (i = 0; i < 1; i++)
+ xprintf(" %2d: %08x\n", i, cc[i]);
+ break;
+
+ default: /* NYI: K_DH_*_GEN, K_RSA_*_OP, K_DSA_*, K_MOD_* */
+ xprintf(" %04x\n", op);
+ for (i = 0; i < cc_words; i++)
+ xprintf(" %2d: %08x\n", i, cc[i]);
+ break;
+ }
+ return chain_out;
+}
+
+static void
+bcm5821_dump_pkt (uint32_t *pkt, int port)
+{
+ uint32_t *cc = PHYS_TO_PTR(PCI_TO_PHYS(pkt[0]));
+ uint32_t *chain;
+ int chain_out;
+ int i, j;
+
+ xprintf(" %2d: %08x ", 0, pkt[0]);
+ chain_out = (port == 1 ? bcm5821_dump_cc1 : bcm5821_dump_cc2)(cc);
+
+ for (i = 1; i < PD_SIZE/4; i++) {
+ xprintf(" %2d: %08x\n", i, pkt[i]);
+
+ if (pkt[i] != 0) {
+ switch (i) {
+ case 2:
+ chain = PHYS_TO_PTR(PCI_TO_PHYS(pkt[i]));
+ for (j = 0; j < CHAIN_WORDS; j++)
+ xprintf(" %2d: %08x\n", j, chain[j]);
+ break;
+ case 6:
+ if (chain_out) {
+ chain = PHYS_TO_PTR(PCI_TO_PHYS(pkt[i]));
+ for (j = 0; j < CHAIN_WORDS; j++)
+ xprintf(" %2d: %08x\n", j, chain[j]);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+static void
+bcm5821_dump_mcr (uint32_t mcr[], int port)
+{
+ unsigned i;
+ unsigned npkts = G_MCR_NUM_PACKETS(mcr[0]);
+
+ xprintf("MCR header %08x at %p:\n", mcr[0], mcr);
+ for (i = 0; i < npkts; i++) {
+ xprintf(" packet %d:\n", i+1);
+ bcm5821_dump_pkt(&mcr[1 + i*(PD_SIZE/4)], port);
+ }
+}
+
+
+static void
+bcm5821_show_pkt1 (uint32_t *pkt)
+{
+ uint32_t *cc = PHYS_TO_PTR(PCI_TO_PHYS(pkt[0]));
+ unsigned op = G_CC_OPCODE(cc[0]);
+ int i;
+
+ switch (op) {
+ case K_SSL_MAC:
+ {
+ uint32_t *hash = PHYS_TO_PTR(PCI_TO_PHYS(pkt[6]));
+ xprintf("SSL_MAC hash:\n");
+ xprintf(" %08x %08x %08x %08x\n",
+ hash[0], hash[1], hash[2], hash[3]);
+ xprintf(" %08x\n", hash[4]);
+ }
+ break;
+ case K_TLS_HMAC:
+ {
+ uint32_t *hash = PHYS_TO_PTR(PCI_TO_PHYS(pkt[7]));
+ xprintf("TLS_HMAC hash:\n");
+ xprintf(" %08x %08x %08x %08x\n",
+ hash[0], hash[1], hash[2], hash[3]);
+ xprintf(" %08x\n", hash[4]);
+ }
+ break;
+ case K_ARC4:
+ {
+ uint32_t *output = PHYS_TO_PTR(PCI_TO_PHYS(pkt[5]));
+ uint32_t *chain = PHYS_TO_PTR(PCI_TO_PHYS(pkt[6]));
+ uint32_t *update = PHYS_TO_PTR(PCI_TO_PHYS(chain[0]));
+
+ xprintf("ARCFOUR output\n");
+ for (i = 0; i < 64; i += 4)
+ xprintf (" %08x %08x %08x %08x\n",
+ output[i+0], output[i+1], output[i+2], output[i+3]);
+ xprintf("ARCFOUR update\n");
+ xprintf(" %08x\n", update[0]);
+ for (i = 0; i < 256/4; i += 4)
+ xprintf (" %08x %08x %08x %08x\n",
+ update[i+1], update[i+2], update[i+3], update[i+4]);
+ }
+ break;
+ case K_HASH:
+ {
+ uint8_t *digest = PHYS_TO_PTR(PCI_TO_PHYS(pkt[6]));
+
+ xprintf("HASH digest ");
+ for (i = 0; i < 16; i++)
+ xprintf("%02x", digest[i]);
+ xprintf("\n");
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+bcm5821_show_pkt2 (uint32_t *pkt)
+{
+ uint32_t *cc = PHYS_TO_PTR(PCI_TO_PHYS(pkt[0]));
+ unsigned op = G_CC_OPCODE(cc[0]);
+ int i;
+
+ switch (op) {
+ case K_RNG_DIRECT:
+ case K_RNG_SHA1:
+ {
+ uint32_t *output = PHYS_TO_PTR(PCI_TO_PHYS(pkt[5]));
+ size_t len = V_DBC_DATA_LEN(pkt[7])/sizeof(uint32_t);
+
+ xprintf("RNG output\n");
+ for (i = 0; i < len; i += 4)
+ xprintf (" %08x %08x %08x %08x\n",
+ output[i+0], output[i+1], output[i+2], output[i+3]);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+bcm5821_show_mcr (uint32_t mcr[], int port)
+{
+ unsigned i;
+ unsigned npkts = G_MCR_NUM_PACKETS(mcr[0]);
+
+ xprintf("MCR at %p:\n", mcr);
+ for (i = 0; i < npkts; i++) {
+ xprintf("packet %d:\n", i+1);
+ if (port == 1)
+ bcm5821_show_pkt1(&mcr[1 + i*(PD_SIZE/4)]);
+ else
+ bcm5821_show_pkt2(&mcr[1 + i*(PD_SIZE/4)]);
+ }
+}
+
+
+static uint32_t *
+bcm5821_alloc_hash (const uint8_t *msg, size_t msg_len, int swap)
+{
+ uint32_t *mcr;
+ uint32_t *cmd; /* always reads at least 64 bytes */
+ uint8_t *message;
+ uint8_t *digest;
+ int i;
+
+ message = KMALLOC(msg_len, CACHE_LINE_SIZE);
+ for (i = 0; i < msg_len; i++)
+ message[i] = msg[i];
+
+ digest = KMALLOC(16, CACHE_LINE_SIZE);
+ for (i = 0; i < 16; i++)
+ digest[i] = 0;
+
+ mcr = KMALLOC(MCR_WORDS(1)*4, CACHE_LINE_SIZE);
+ mcr[0] = V_MCR_NUM_PACKETS(1);
+
+ cmd = KMALLOC(64, CACHE_LINE_SIZE); /* Always allocate >= 64 bytes */
+ cmd[0] = V_CC_OPCODE(K_HASH) | V_CC_LEN(8);
+ cmd[1] = V_CC_FLAGS(K_HASH_FLAGS_MD5);
+
+ mcr[1] = PHYS_TO_PCI(PTR_TO_PHYS(cmd));
+
+ /* input fragment */
+ mcr[2] = swap ? PHYS_TO_PCI_D(PTR_TO_PHYS(message))
+ : PHYS_TO_PCI(PTR_TO_PHYS(message));
+ mcr[3] = 0;
+ mcr[4] = V_DBC_DATA_LEN(msg_len);
+
+ mcr[5] = V_PD_PKT_LEN(msg_len);
+
+ mcr[6] = 0;
+ mcr[7] = swap ? PHYS_TO_PCI_D(PTR_TO_PHYS(digest))
+ : PHYS_TO_PCI(PTR_TO_PHYS(digest));
+ mcr[8] = 0;
+
+ return mcr;
+}
+
+static void
+bcm5821_free_hash (uint32_t mcr[])
+{
+ KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[1])));
+ KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[2])));
+ KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[7])));
+
+ KFREE(mcr);
+}
+
+
+static uint32_t *
+bcm5821_alloc_hmac (const char *key, int key_len,
+ const char *msg, int msg_len,
+ int swap)
+{
+ uint32_t *message;
+ uint32_t *cmd;
+ uint32_t *mcr;
+ uint32_t *hash;
+ int i;
+
+ message = KMALLOC(msg_len, CACHE_LINE_SIZE);
+ memcpy((uint8_t *)message, msg, msg_len);
+
+ mcr = KMALLOC(MCR_WORDS(1)*4, CACHE_LINE_SIZE);
+ mcr[0] = V_MCR_NUM_PACKETS(1);
+
+ /* packet 1 */
+
+ cmd = KMALLOC(TLS_HMAC_CMD_WORDS*4, CACHE_LINE_SIZE);
+ cmd[0] = V_CC_OPCODE(K_TLS_HMAC) | V_CC_LEN(TLS_HMAC_CMD_WORDS*4);
+ cmd[1] = V_CC_FLAGS(K_HASH_FLAGS_MD5);
+
+ /* XXX This is not correct. The key is used to compute the inner
+ and outer states. */
+ for (i = 2; i < 7; i++)
+ cmd[i] = 0x36363636; /* XXX MAC write secret */
+ cmd[6] = 0x00000000; /* must be zero for SSL */
+ for (i = 8; i < 13; i++)
+ cmd[i] = 0x5c5c5c5c;
+ cmd[13] = 0; /* seq num */
+ cmd[14] = 1;
+ cmd[15] = 0x03000000 | (msg_len << 8); /* XXX type/len/rsvd */
+
+ mcr[1] = PHYS_TO_PCI(PTR_TO_PHYS(cmd));
+
+ /* input fragment */
+ mcr[2] = swap ? PHYS_TO_PCI_D(PTR_TO_PHYS(message))
+ : PHYS_TO_PCI(PTR_TO_PHYS(message));
+ mcr[3] = 0;
+ mcr[4] = V_DBC_DATA_LEN(msg_len);
+
+ mcr[5] = V_PD_PKT_LEN(msg_len);
+
+ hash = KMALLOC(5*4, CACHE_LINE_SIZE);
+ for (i = 0; i < 5; i++)
+ hash[i] = 0;
+
+ mcr[6] = 0;
+ mcr[7] = swap ? PHYS_TO_PCI_D(PTR_TO_PHYS(hash))
+ : PHYS_TO_PCI(PTR_TO_PHYS(hash));
+ mcr[8] = 0;
+
+ return mcr;
+}
+
+static void
+bcm5821_free_hmac (uint32_t mcr[])
+{
+ KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[1])));
+ KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[2])));
+ KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[7])));
+
+ KFREE(mcr);
+}
+
+
+static int test_init = 0;
+
+/* Timing */
+
+/* For Pass 1, dedicate an SCD peformance counter to use as a counter
+ of ZBbus cycles. */
+#include "sb1250_scd.h"
+#define ZCTR_MODULUS 0x10000000000LL
+
+/* The counter is a shared resource that must be reset periodically
+ since it doesn't roll over. Furthermore, there is a pass one bug
+ that makes the interrupt unreliable and the final value either all
+ ones or all zeros. We therefore reset the count when it exceeds
+ half the modulus. We also assume that intervals of interest
+ are much less than half the modulus and attempt to adjust for
+ the reset in zclk_elapsed. */
+
+static void
+zclk_init(uint64_t val)
+{
+ *((volatile uint64_t *) UNCADDR(A_SCD_PERF_CNT_0)) = val;
+ *((volatile uint64_t *) UNCADDR(A_SCD_PERF_CNT_CFG)) =
+ V_SPC_CFG_SRC0(1) | M_SPC_CFG_ENABLE;
+}
+
+static uint64_t
+zclk_get(void)
+{
+ uint64_t ticks;
+
+ ticks = *((volatile uint64_t *) UNCADDR(A_SCD_PERF_CNT_0));
+ if (ticks == 0 || ticks == ZCTR_MODULUS-1) {
+ ticks = 0;
+ zclk_init(ticks);
+ }
+ else if (ticks >= ZCTR_MODULUS/2) {
+ ticks -= ZCTR_MODULUS/2;
+ zclk_init(ticks); /* Ignore the fudge and lose a few ticks */
+ }
+ return ticks;
+}
+
+static uint64_t
+zclk_elapsed(uint64_t stop, uint64_t start)
+{
+ return ((stop >= start) ? stop : stop + ZCTR_MODULUS/2) - start;
+}
+
+
+/* Auxiliary functions */
+
+static uint32_t *
+bcm5821_alloc_composite(int input_size)
+{
+ uint32_t *input, *output;
+ uint32_t *cmd;
+ uint32_t *chain;
+ uint32_t *mcr;
+ uint32_t *hash;
+ uint32_t *update;
+ uint8_t *arc4_state;
+ int i;
+
+ input = KMALLOC(input_size, CACHE_LINE_SIZE);
+ for (i = 0; i < input_size; i++)
+ ((uint8_t *)input)[i] = i & 0xFF;
+ output = KMALLOC(input_size + 16, CACHE_LINE_SIZE);
+ for (i = 0; i < input_size + 16; i++)
+ ((uint8_t *)output)[i] = 0xFF;
+
+ mcr = KMALLOC(MCR_WORDS(2)*4, CACHE_LINE_SIZE);
+ mcr[0] = V_MCR_NUM_PACKETS(2);
+
+ /* packet 1 */
+
+ cmd = KMALLOC(SSL_MAC_CMD_WORDS*4, CACHE_LINE_SIZE);
+ cmd[0] = V_CC_OPCODE(K_SSL_MAC) | V_CC_LEN(SSL_MAC_CMD_WORDS*4);
+ cmd[1] = V_CC_FLAGS(K_HASH_FLAGS_MD5);
+ for (i = 2; i < 6; i++)
+ cmd[i] = 0x01020304; /* XXX MAC write secret */
+ cmd[6] = 0x00000000; /* must be zero for SSL */
+ for (i = 7; i < 19; i++)
+ cmd[i] = 0x36363636;
+ cmd[19] = 0; /* seq num */
+ cmd[20] = 1;
+ cmd[21] = 0x03000000 | (input_size << 8); /* type/len/rsvd */
+
+ mcr[1] = PHYS_TO_PCI(PTR_TO_PHYS(cmd));
+
+ /* input fragment */
+ mcr[2] = PHYS_TO_PCI(PTR_TO_PHYS(input));
+ mcr[3] = 0;
+ mcr[4] = V_DBC_DATA_LEN(input_size);
+
+ mcr[5] = V_PD_PKT_LEN(input_size);
+
+ hash = KMALLOC(5*4, CACHE_LINE_SIZE);
+ for (i = 0; i < 5; i++)
+ hash[i] = 0;
+
+ mcr[6] = 0;
+ mcr[7] = PHYS_TO_PCI(PTR_TO_PHYS(hash));
+ mcr[8] = 0;
+
+ /* packet 2 */
+
+ cmd = KMALLOC(ARC4_CMD_WORDS*4, CACHE_LINE_SIZE);
+ cmd[0] = V_CC_OPCODE(K_ARC4) | V_CC_LEN(ARC4_CMD_WORDS*4);
+ cmd[1] = M_ARC4_FLAGS_WRITEBACK;
+ cmd[2] = 0x000100F3;
+ arc4_state = (uint8_t *)&cmd[3];
+ for (i = 0; i < 256; i++)
+ arc4_state[i] = i;
+
+ mcr[8+1] = PHYS_TO_PCI(PTR_TO_PHYS(cmd));
+
+ /* input fragment */
+ chain = KMALLOC(CHAIN_WORDS*4, CACHE_LINE_SIZE);
+
+ mcr[8+2] = PHYS_TO_PCI(PTR_TO_PHYS(input));
+ mcr[8+3] = PHYS_TO_PCI(PTR_TO_PHYS(chain));
+ mcr[8+4] = V_DBC_DATA_LEN(input_size);
+
+ /* MAC fragment */
+ chain[0] = PHYS_TO_PCI(PTR_TO_PHYS(hash));
+ chain[1] = 0;
+ chain[2] = V_DBC_DATA_LEN(16);
+
+ mcr[8+5] = V_PD_PKT_LEN(input_size + 16);
+
+ /* output fragment */
+ chain = KMALLOC(CHAIN_WORDS*4, CACHE_LINE_SIZE);
+
+ mcr[8+6] = PHYS_TO_PCI(PTR_TO_PHYS(output));
+ mcr[8+7] = PHYS_TO_PCI(PTR_TO_PHYS(chain));
+ mcr[8+8] = V_DBC_DATA_LEN(input_size + 16);
+
+ update = KMALLOC(ARC4_STATE_WORDS*4, CACHE_LINE_SIZE);
+ for (i = 0; i < ARC4_STATE_WORDS; i++)
+ update[i] = 0xFFFFFFFF;
+
+ /* output update */
+ chain[0] = PHYS_TO_PCI(PTR_TO_PHYS(update));
+ chain[1] = 0;
+ chain[2] = V_DBC_DATA_LEN(ARC4_STATE_WORDS*4); /* not actually used */
+
+ return mcr;
+}
+
+static void
+bcm5821_free_composite (uint32_t mcr[])
+{
+ uint32_t *chain;
+
+ /* packet 1 */
+
+ KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[1])));
+ KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[2])));
+ KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[7])));
+
+ /* packet 2 */
+ KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[8+1])));
+ /* mcr[8+2] already freed */
+ chain = PHYS_TO_PTR(PCI_TO_PHYS(mcr[8+3]));
+ KFREE(PHYS_TO_PTR(PCI_TO_PHYS(chain[0]))); KFREE(chain);
+ KFREE(PHYS_TO_PTR(PCI_TO_PHYS(mcr[8+6])));
+ chain = PHYS_TO_PTR(PCI_TO_PHYS(mcr[8+7]));
+ KFREE(PHYS_TO_PTR(PCI_TO_PHYS(chain[0]))); KFREE(chain);
+
+ KFREE(mcr);
+}
+
+
+static void
+flush_l2(void)
+{
+ /* Temporary hack: churn through all of L2 */
+ volatile uint64_t *lomem;
+ uint64_t t;
+ int i;
+
+ lomem = (uint64_t *)(0xFFFFFFFF80000000LL); /* kseg0 @ 0 */
+ t = 0;
+ for (i = 0; i < (512/8)*1024; i++)
+ t ^= lomem[i];
+}
+
+#ifdef IRQ
+static void
+bcm5821_interrupt(void *ctx)
+{
+}
+#endif
+
+
+#define POOL_SIZE 4
+#define MCR_QUEUE_DEPTH 2
+
+static int
+bcm5821_composite (bcm5821_state_t *sc, size_t len, int trials)
+{
+ uint32_t *mcr[POOL_SIZE];
+ uint32_t status;
+ uint64_t start, stop, ticks;
+ uint64_t tpb, Mbs;
+ int i;
+ int next, last, run;
+
+ for (i = 0; i < POOL_SIZE; i++)
+ mcr[i] = bcm5821_alloc_composite(len);
+
+ (void)bcm5821_dump_mcr; /*bcm5821_dump_mcr(mcr[0], 1);*/
+
+ next = last = 0;
+ run = 0;
+
+ /* Force all descriptors and buffers out of L1 */
+ cfe_flushcache(CFE_CACHE_FLUSH_D);
+ (void)flush_l2; /* XXX for now */
+
+ status = READCSR(sc, R_DMA_STAT);
+ WRITECSR(sc, R_DMA_STAT, status); /* clear pending bits */
+ status = READCSR(sc, R_DMA_STAT);
+
+ for (i = 0; i < 1000; i++) {
+ status = READCSR(sc, R_DMA_STAT);
+ if ((status & M_DMA_STAT_MCR1_FULL) == 0)
+ break;
+ cfe_sleep(1);
+ }
+ if (i == 1000) {
+ dumpcsrs(sc, "bcm5821: full bit never clears");
+ return -1;
+ }
+
+#ifdef IRQ
+ /* Enable interrupt polling, but the handler is never called. */
+ cfe_request_irq(sc->irq, bcm5821_interrupt, NULL, 0, 0);
+#endif
+
+ zclk_init(0); /* Time origin is arbitrary. */
+ start = zclk_get();
+
+ /* MCR ports are double buffered. */
+ for (i = 0; i < MCR_QUEUE_DEPTH; i++) {
+ while ((READCSR(sc, R_DMA_STAT) & M_DMA_STAT_MCR1_FULL) != 0)
+ continue;
+ WRITECSR(sc, R_MCR1, PHYS_TO_PCI(PTR_TO_PHYS(mcr[next])));
+ next = (next + 1) % POOL_SIZE;
+ }
+
+ while (1) {
+#ifdef IRQ
+ while ((_getcause() & M_CAUSE_IP2) == 0)
+ continue;
+
+ status = READCSR(sc, R_DMA_STAT);
+ if ((status & M_DMA_STAT_MCR1_INTR) == 0) {
+ /* This apparently is MCR1_ALL_EMPTY, timing of which is unclear. */
+ WRITECSR(sc, R_DMA_STAT,
+ M_DMA_STAT_DMAERR_INTR | M_DMA_STAT_MCR1_INTR);
+ continue;
+ }
+
+ stop = zclk_get();
+ WRITECSR(sc, R_DMA_STAT,
+ M_DMA_STAT_DMAERR_INTR | M_DMA_STAT_MCR1_INTR);
+#else
+ volatile uint32_t *last_mcr = mcr[last];
+
+ while ((*last_mcr & M_MCR_DONE) == 0)
+ continue;
+
+ stop = zclk_get();
+#endif
+
+ run++;
+ if (run == trials)
+ break;
+
+ while ((READCSR(sc, R_DMA_STAT) & M_DMA_STAT_MCR1_FULL) != 0)
+ continue;
+ WRITECSR(sc, R_MCR1, PHYS_TO_PCI(PTR_TO_PHYS(mcr[next])));
+ next = (next + 1) % POOL_SIZE;
+
+ /* Clear the DONE and ERROR bits. This will bring one line of
+ the MCR back into L1. Flush? */
+ mcr[last][0] = V_MCR_NUM_PACKETS(2);
+ last = (last + 1) % POOL_SIZE;
+ }
+
+#ifdef IRQ
+ status = READCSR(sc, R_DMA_STAT);
+ WRITECSR(sc, R_DMA_STAT, status); /* clear pending bits */
+ cfe_free_irq(sc->irq, 0);
+#endif
+
+ ticks = zclk_elapsed(stop, start) / trials;
+ xprintf("bcm5821: Composite %lld ticks for %d bytes, %d packets\n",
+ ticks, len, trials);
+ /* Scaling for two decimal places. */
+ tpb = (ticks*100) / len;
+ Mbs = (2000*100)*100 / tpb;
+ xprintf(" rate %lld.%02lld Mbps\n", Mbs/100, Mbs % 100);
+
+ if (trials == 1)
+ {
+ bcm5821_show_mcr(mcr[0], 1);
+ }
+
+ for (i = 0; i < POOL_SIZE; i++)
+ bcm5821_free_composite(mcr[i]);
+
+ return 0;
+}
+
+
+/* The following code depends on having a separate interrupt per
+ device, and there are only 4 PCI interrupts. */
+#define MAX_DEVICES 4
+
+struct dev_info {
+ bcm5821_state_t *sc;
+ uint64_t irq_mask;
+ int index[MCR_QUEUE_DEPTH];
+};
+
+
+#define N_DEVICES 2
+
+static int
+bcm5821_composite2 (bcm5821_state_t *sc0, bcm5821_state_t *sc1,
+ size_t len, int trials)
+{
+ uint32_t *mcr[POOL_SIZE];
+ uint32_t ring[POOL_SIZE];
+ uint32_t status;
+ uint64_t start, stop, ticks;
+ uint64_t tpb, Mbs;
+ int i;
+ int next, last;
+ int started, run;
+ int d;
+ struct dev_info dev[N_DEVICES];
+ uint64_t masks;
+ bcm5821_state_t *sc;
+#ifdef IRQ
+ volatile uint64_t *irqstat = IMR_POINTER(0, R_IMR_INTERRUPT_SOURCE_STATUS);
+#endif
+ uint64_t pending;
+
+ dev[0].sc = sc0; dev[1].sc = sc1;
+
+ for (i = 0; i < POOL_SIZE; i++)
+ mcr[i] = bcm5821_alloc_composite(len);
+ for (i = 0; i < POOL_SIZE; i++)
+ ring[i] = i;
+ next = last = 0;
+
+ (void)bcm5821_dump_mcr; /*bcm5821_dump_mcr(mcr[0], 1);*/
+
+ started = run = 0;
+
+ /* Force all descriptors and buffers out of L1 */
+ cfe_flushcache(CFE_CACHE_FLUSH_D);
+ (void)flush_l2; /* XXX for now */
+
+ masks = 0;
+ for (d = 0; d < N_DEVICES; d++) {
+ sc = dev[d].sc;
+ dev[d].irq_mask = 1LL << (sc->irq);
+ masks |= dev[d].irq_mask;
+
+ status = READCSR(sc, R_DMA_STAT);
+ WRITECSR(sc, R_DMA_STAT, status); /* clear pending bits */
+ status = READCSR(sc, R_DMA_STAT);
+
+ for (i = 0; i < 1000; i++) {
+ status = READCSR(sc, R_DMA_STAT);
+ if ((status & M_DMA_STAT_MCR1_FULL) == 0)
+ break;
+ cfe_sleep(1);
+ }
+
+ if (i == 1000) {
+ dumpcsrs(sc, "bcm5821: full bit never clears");
+ return -1;
+ }
+
+#ifdef IRQ
+ /* Enable interrupt polling, but the handler is never called. */
+ cfe_request_irq(sc->irq, bcm5821_interrupt, NULL, 0, 0);
+#endif
+ }
+
+ stop = 0; /* Keep compiler happy */
+ zclk_init(0); /* Time origin is arbitrary. */
+ start = zclk_get();
+
+ for (d = 0; d < N_DEVICES; d++) {
+ sc = dev[d].sc;
+
+ /* MCR ports are double buffered. */
+ for (i = 0; i < 2; i++) {
+ int index = ring[next];
+ while ((READCSR(sc, R_DMA_STAT) & M_DMA_STAT_MCR1_FULL) != 0)
+ continue;
+ WRITECSR(sc, R_MCR1, PHYS_TO_PCI(PTR_TO_PHYS(mcr[index])));
+ dev[d].index[i] = index;
+ next = (next + 1) % POOL_SIZE;
+ started++;
+ }
+ }
+
+ while (trials == 0 || run != trials) {
+#ifdef IRQ
+ while ((_getcause() & M_CAUSE_IP2) == 0)
+ continue;
+
+ pending = *irqstat;
+#else
+ pending = 0;
+ while (pending == 0) {
+ for (d = 0; d < N_DEVICES; d++) {
+ volatile uint32_t *last_mcr = mcr[dev[d].index[0]];
+
+ if ((*last_mcr & M_MCR_DONE) != 0)
+ pending |= dev[d].irq_mask;
+ }
+ }
+#endif
+
+ stop = zclk_get();
+
+ for (d = 0; d < N_DEVICES; d++) {
+ if ((dev[d].irq_mask & pending) != 0) {
+ sc = dev[d].sc;
+
+#ifdef IRQ
+ status = READCSR(sc, R_DMA_STAT);
+ if ((status & M_DMA_STAT_MCR1_INTR) == 0) {
+ /* Apparently MCR1_ALL_EMPTY, timing of which is unclear. */
+ WRITECSR(sc, R_DMA_STAT,
+ M_DMA_STAT_DMAERR_INTR | M_DMA_STAT_MCR1_INTR);
+ continue;
+ }
+ WRITECSR(sc, R_DMA_STAT,
+ M_DMA_STAT_DMAERR_INTR | M_DMA_STAT_MCR1_INTR);
+#endif
+ ring[last] = dev[d].index[0];
+ /* Clear the DONE and ERROR bits. This will bring one line of
+ the MCR back into L1. Flush? */
+ mcr[ring[last]][0] = V_MCR_NUM_PACKETS(2);
+ last = (last + 1) % POOL_SIZE;
+
+ run++;
+ if (run == trials)
+ break;
+
+ dev[d].index[0] = dev[d].index[1];
+ if (trials == 0 || started < trials) {
+ int index = ring[next];
+ while ((READCSR(sc, R_DMA_STAT) & M_DMA_STAT_MCR1_FULL) != 0)
+ continue;
+ WRITECSR(sc, R_MCR1, PHYS_TO_PCI(PTR_TO_PHYS(mcr[index])));
+ dev[d].index[1] = index;
+ next = (next + 1) % POOL_SIZE;
+ started++;
+ }
+ }
+ }
+ }
+
+ for (d = 0; d < N_DEVICES; d++) {
+ sc = dev[d].sc;
+ status = READCSR(sc, R_DMA_STAT);
+ WRITECSR(sc, R_DMA_STAT, status); /* clear pending bits */
+#ifdef IRQ
+ cfe_free_irq(sc->irq, 0);
+#endif
+ }
+
+ ticks = zclk_elapsed(stop, start) / trials;
+ xprintf("bcm5821: Composite %lld ticks for %d bytes, %d packets\n",
+ ticks, len, trials);
+ /* Scaling for two decimal places. */
+ tpb = (ticks*100) / len;
+ Mbs = (2000*100)*100 / tpb;
+ xprintf(" rate %lld.%02lld Mbps\n", Mbs/100, Mbs % 100);
+
+ for (i = 0; i < POOL_SIZE; i++)
+ bcm5821_free_composite(mcr[i]);
+
+ return 0;
+}
+
+
+extern cfe_devctx_t *cfe_handle_table[];
+
+int bcm5821_test (int device, int trials);
+int
+bcm5821_test (int device, int trials)
+{
+ cfe_devctx_t *ctx = cfe_handle_table[device];
+ bcm5821_state_t *sc = ctx->dev_softc;
+
+ if (!test_init) {
+ zclk_init(0); /* Time origin is arbitrary */
+ test_init = 1;
+ }
+
+ bcm5821_composite(sc, 1472, trials);
+
+ return 0;
+}
+
+int bcm5821_test2 (int device0, int device2, int trials);
+int
+bcm5821_test2 (int device0, int device1, int trials)
+{
+ cfe_devctx_t *ctx0 = cfe_handle_table[device0];
+ cfe_devctx_t *ctx1 = cfe_handle_table[device1];
+ bcm5821_state_t *sc0 = ctx0->dev_softc;
+ bcm5821_state_t *sc1 = ctx1->dev_softc;
+
+ if (!test_init) {
+ zclk_init(0); /* Time origin is arbitrary */
+ test_init = 1;
+ }
+
+ bcm5821_composite2(sc0, sc1, 1472, trials);
+
+ return 0;
+}
+
+
+static int
+bcm5821_hash_md5 (bcm5821_state_t *sc, const char *msg)
+{
+ size_t len = strlen(msg);
+ uint32_t *mcr;
+ uint32_t status;
+ int i;
+ int swap = (sc->device == K_PCI_ID_BCM5820);
+
+ mcr = bcm5821_alloc_hash(msg, len, swap);
+
+ /* bcm5821_dump_mcr(mcr, 1); */
+
+ status = READCSR(sc, R_DMA_STAT);
+ WRITECSR(sc, R_DMA_STAT, status); /* clear pending bits */
+ status = READCSR(sc, R_DMA_STAT);
+
+ for (i = 0; i < 1000; i++) {
+ status = READCSR(sc, R_DMA_STAT);
+ if ((status & M_DMA_STAT_MCR1_FULL) == 0)
+ break;
+ cfe_sleep(1);
+ }
+ if (i == 1000) {
+ dumpcsrs(sc, "bcm5821: full bit never clears");
+ return -1;
+ }
+
+ WRITECSR(sc, R_MCR1, PHYS_TO_PCI(PTR_TO_PHYS(mcr)));
+
+ for (i = 0; i < 1000; i++) {
+#ifdef IRQ
+ status = READCSR(sc, R_DMA_STAT);
+ if ((status & M_DMA_STAT_MCR1_INTR) != 0)
+ break;
+#else
+ if ((mcr[0] & M_MCR_DONE) != 0)
+ break;
+#endif
+ cfe_sleep(1);
+ }
+ if (i == 1000) {
+ dumpcsrs(sc, "bcm5821: done bit never sets");
+ /*return -1;*/
+ }
+
+ status = READCSR(sc, R_DMA_STAT);
+ WRITECSR(sc, R_DMA_STAT, status); /* clear pending bits */
+
+ /* bcm5821_dump_mcr(mcr, 1); */
+
+ bcm5821_show_mcr(mcr, 1);
+
+ bcm5821_free_hash(mcr);
+
+ return 0;
+}
+
+
+static int
+bcm5821_hmac_md5 (bcm5821_state_t *sc,
+ const uint8_t key[], size_t key_len,
+ const uint8_t data[], size_t data_len)
+{
+ uint32_t *mcr;
+ uint32_t status;
+ int i;
+ int swap = (sc->device == K_PCI_ID_BCM5820);
+
+ mcr = bcm5821_alloc_hmac(key, key_len, data, data_len, swap);
+
+ status = READCSR(sc, R_DMA_STAT);
+ WRITECSR(sc, R_DMA_STAT, status); /* clear pending bits */
+ status = READCSR(sc, R_DMA_STAT);
+
+ for (i = 0; i < 1000; i++) {
+ status = READCSR(sc, R_DMA_STAT);
+ if ((status & M_DMA_STAT_MCR1_FULL) == 0)
+ break;
+ cfe_sleep(1);
+ }
+ if (i == 1000) {
+ dumpcsrs(sc, "bcm5821: full bit never clears");
+ return -1;
+ }
+#if 0 /* disable: work in progress */
+
+ while ((READCSR(sc, R_DMA_STAT) & M_DMA_STAT_MCR1_FULL) != 0)
+ continue;
+ WRITECSR(sc, R_MCR1, PHYS_TO_PCI(PTR_TO_PHYS(mcr)));
+
+ for (i = 0; i < 1000; i++) {
+ if ((mcr[0] & M_MCR_DONE) != 0)
+ break;
+ cfe_sleep(1);
+ }
+ if (i == 1000) {
+ dumpcsrs(sc, "bcm5821: done bit never sets");
+ return -1;
+ }
+
+ status = READCSR(sc, R_DMA_STAT);
+ WRITECSR(sc, R_DMA_STAT, status); /* clear pending bits */
+
+ bcm5821_show_mcr(mcr, 1);
+#endif
+
+ bcm5821_free_hmac(mcr);
+ return 0;
+}
+
+/* Sanity check on the implementation using RFC test suites. */
+
+int bcm5821_check (int device);
+int
+bcm5821_check (int device)
+{
+ static unsigned char k1[16] = {
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b
+ };
+ static unsigned char m1[] = "Hi There";
+
+ static unsigned char k2[] = "Jefe";
+ static unsigned char m2[] = "what do ya want for nothing?";
+
+ static unsigned char k3[16] = {
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA
+ };
+ static unsigned char m3[50] = {
+ 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+ 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+ 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+ 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+ 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD
+ };
+
+ cfe_devctx_t *ctx = cfe_handle_table[device];
+ bcm5821_state_t *sc = ctx->dev_softc;
+
+ if (!test_init) {
+ zclk_init(0); /* Time origin is arbitrary */
+ test_init = 1;
+ }
+
+#if 0 /* 5821 cannot handle 0-length fragments (see Appendix B) */
+ bcm5821_hash_md5(sc, "");
+#endif
+ bcm5821_hash_md5(sc, "a");
+ bcm5821_hash_md5(sc, "abc");
+ bcm5821_hash_md5(sc, "message digest");
+ bcm5821_hash_md5(sc, "abcdefghijklmnopqrstuvwxyz");
+ bcm5821_hash_md5(sc, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
+ bcm5821_hash_md5(sc, "12345678901234567890123456789012345678901234567890123456789012345678901234567890");
+
+ bcm5821_hmac_md5(sc, k1, sizeof(k1), m1, strlen(m1));
+ bcm5821_hmac_md5(sc, k2, strlen(k2), m2, strlen(m2));
+ bcm5821_hmac_md5(sc, k3, sizeof(k3), m3, sizeof(m3));
+
+ return 0;
+}
+
+/* Output of md5 test suite (md5 -x)
+
+MD5 test suite:
+MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
+MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
+MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
+MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
+MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
+MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = d174ab98d277d9f5a5611c2c9f419d9f
+MD5 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 57edf4a22be3c955ac49da2e2107b67a
+
+*/
+
+/* HMAC-MD5 test suite
+
+Test Vectors (Trailing '\0' of a character string not included in test):
+
+ key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+ key_len = 16 bytes
+ data = "Hi There"
+ data_len = 8 bytes
+ digest = 0x9294727a3638bb1c13f48ef8158bfc9d
+
+ key = "Jefe"
+ data = "what do ya want for nothing?"
+ data_len = 28 bytes
+ digest = 0x750c783e6ab0b503eaa86e310a5db738
+
+ key = 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ key_len 16 bytes
+ data = 0xDDDDDDDDDDDDDDDDDDDD...
+ ..DDDDDDDDDDDDDDDDDDDD...
+ ..DDDDDDDDDDDDDDDDDDDD...
+ ..DDDDDDDDDDDDDDDDDDDD...
+ ..DDDDDDDDDDDDDDDDDDDD
+ data_len = 50 bytes
+ digest = 0x56be34521d144c88dbb8c733f0e8b3f6
+
+*/
+#endif /* !_BCM14XX_ */
+
+
+#if 0 /* ---------- XXX still under construction XXX ---------- */
+
+static uint32_t *
+bcm5821_alloc_rng (int output_size)
+{
+ uint32_t *output;
+ uint32_t *mcr;
+ uint32_t *cmd;
+ int i;
+
+ output = (uint32_t *)KMALLOC(output_size, CACHE_LINE_SIZE);
+ for (i = 0; i < output_size/sizeof(uint32_t); i++)
+ output[i] = 0xDEADBEEF;
+
+ mcr = KMALLOC(MCR_WORDS(1)*4, CACHE_LINE_SIZE);
+ mcr[0] = V_MCR_NUM_PACKETS(1);
+
+ cmd = KMALLOC(16, CACHE_LINE_SIZE); /* Always allocate >= 64 bytes */
+ cmd[0] = V_CC_OPCODE(K_RNG_DIRECT) | V_CC_LEN(4);
+
+ mcr[1] = PHYS_TO_PCI(PTR_TO_PHYS(cmd));
+
+ /* input fragment */
+ mcr[2] = 0;
+ mcr[3] = 0;
+ mcr[4] = V_DBC_DATA_LEN(0);
+
+ mcr[5] = V_PD_PKT_LEN(output_size);
+
+ /* output fragment */
+ mcr[6] = PHYS_TO_PCI(PTR_TO_PHYS(output));
+ mcr[7] = 0;
+ mcr[8] = V_DBC_DATA_LEN(sizeof(output));
+
+ return mcr;
+}
+
+
+static uint32_t *
+bcm5821_alloc_ssl_mac (int msg_size)
+{
+ uint32_t *message;
+ uint32_t *cmd;
+ uint32_t *mcr;
+ uint32_t *hash;
+ int i;
+
+ message = KMALLOC(msg_size, CACHE_LINE_SIZE);
+ for (i = 0; i < msg_size; i++)
+ ((uint8_t *)message)[i] = i & 0xFF; /* was 0xDEADBEEF */
+
+ mcr = KMALLOC(MCR_WORDS(1)*4, CACHE_LINE_SIZE);
+ mcr[0] = V_MCR_NUM_PACKETS(1);
+
+ /* packet 1 */
+
+ cmd = KMALLOC(SSL_MAC_CMD_WORDS*4, CACHE_LINE_SIZE);
+ cmd[0] = V_CC_OPCODE(K_SSL_MAC) | V_CC_LEN(SSL_MAC_CMD_WORDS*4);
+ cmd[1] = V_CC_FLAGS(K_HASH_FLAGS_MD5);
+ for (i = 2; i < 6; i++)
+ cmd[i] = 0x01020304; /* XXX MAC write secret */
+ cmd[6] = 0x00000000; /* must be zero for SSL */
+ for (i = 7; i < 19; i++)
+ cmd[i] = 0x36363636;
+ cmd[19] = 0; /* seq num */
+ cmd[20] = 1;
+ cmd[21] = 0x03000000 | (msg_size << 8); /* type/len/rsvd */
+
+ mcr[1] = PHYS_TO_PCI(PTR_TO_PHYS(cmd));
+
+ /* input fragment */
+ mcr[2] = PHYS_TO_PCI(PTR_TO_PHYS(message));
+ mcr[3] = 0;
+ mcr[4] = V_DBC_DATA_LEN(msg_size);
+
+ mcr[5] = V_PD_PKT_LEN(msg_size);
+
+ hash = KMALLOC(5*4, CACHE_LINE_SIZE);
+ for (i = 0; i < 5; i++)
+ hash[i] = 0;
+
+ mcr[6] = 0;
+ mcr[7] = PHYS_TO_PCI(PTR_TO_PHYS(hash));
+ mcr[8] = 0;
+
+ return mcr;
+}
+
+static uint32_t *
+bcm5821_alloc_arc4 (int input_size)
+{
+ uint32_t *mcr;
+ uint32_t cmd[3 + 256/4];
+ uint32_t input[64], output[64];
+ uint32_t chain[3];
+ uint32_t update[1 + 256/4];
+ uint32_t status;
+ uint8_t *arc4_state;
+ int i;
+
+ xprintf("\nARC4\n");
+
+ status = READCSR(sc, R_DMA_STAT);
+ WRITECSR(sc, R_DMA_STAT, status); /* clear pending bits */
+ status = READCSR(sc, R_DMA_STAT);
+
+ for (i = 0; i < 64; i++)
+#if 0
+ input[i] = (i << 24) | ((i+1) << 16) | ((i+2) << 8) | (i+3);
+#else
+ input[i] = 0x5555AAAA;
+#endif
+ for (i = 0; i < 64; i++)
+ output[i] = 0xDEADBEEF;
+ for (i = 0; i < 1 + 256/4; i++)
+ update[i] = 0xFEEDFACE;
+
+ cmd[0] = V_CC_OPCODE(K_ARC4) | V_CC_LEN(sizeof(cmd));
+ cmd[1] = M_ARC4_FLAGS_WRITEBACK;
+#if 0
+ cmd[2] = 0x000100F3;
+#else
+ cmd[2] = 0x00000000;
+#endif
+ arc4_state = (uint8_t *)&cmd[3];
+ for (i = 0; i < 256; i++)
+ arc4_state[i] = i;
+
+ mcr[0] = V_MCR_NUM_PACKETS(1);
+
+ /* packet 1 */
+ mcr[1] = PHYS_TO_PCI(PTR_TO_PHYS(cmd));
+
+ /* input fragment */
+ mcr[2] = PHYS_TO_PCI(PTR_TO_PHYS(input));
+ mcr[3] = 0;
+ mcr[4] = V_DBC_DATA_LEN(sizeof(input));
+
+ mcr[5] = V_PD_PKT_LEN(sizeof(input));
+
+ /* output fragment */
+ mcr[6] = PHYS_TO_PCI(PTR_TO_PHYS(output));
+ mcr[7] = PHYS_TO_PCI(PTR_TO_PHYS(chain));
+ mcr[8] = V_DBC_DATA_LEN(sizeof(output));
+
+ /* output update */
+ chain[0] = PHYS_TO_PCI(PTR_TO_PHYS(update));
+ chain[1] = 0;
+ chain[2] = V_DBC_DATA_LEN(sizeof(update)); /* not actually used */
+
+ return mcr;
+}
+#endif /* 0 */
diff --git a/cfe/cfe/dev/dev_dc21143.c b/cfe/cfe/dev/dev_dc21143.c
new file mode 100644
index 0000000..f133cbb
--- /dev/null
+++ b/cfe/cfe/dev/dev_dc21143.c
@@ -0,0 +1,2388 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * DC2114x Ethernet Driver File: dev_dc21143.c
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "sbmips.h"
+
+#ifndef _SB_MAKE64
+#define _SB_MAKE64(x) ((uint64_t)(x))
+#endif
+#ifndef _SB_MAKEMASK1
+#define _SB_MAKEMASK1(n) (_SB_MAKE64(1) << _SB_MAKE64(n))
+#endif
+
+#include "lib_types.h"
+#include "lib_hssubr.h"
+#include "lib_malloc.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+#include "lib_queue.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+#include "cfe_timer.h"
+#include "cfe_irq.h"
+
+#include "pcivar.h"
+#include "pcireg.h"
+
+#include "dc21143.h"
+#include "mii.h"
+
+/* This is a driver for specific configurations of the DC21041,
+ DC21140A and DC21143, not a generic Tulip driver. The prefix
+ "tulip_" is used to indicate generic Tulip functions, while
+ "dc21041_", "dc21140_" or "dc21143_" indicates functions specific
+ to a chip variant.
+
+ The 21041 driver assumes a 10BT HD interface, since autonegotiation
+ is known to be broken in the early revisons of that chip. Example
+ cards come from DEC.
+
+ The 21140 driver assumes that the PHY uses a standard MII interface
+ for both 100BT and 10BT. Example cards come from DEC (National DP83840
+ Twister PHY) and Netgear (Level One PHY).
+
+ The 21143 driver assumes that the PHY uses the SYM ("5 wire") interface
+ for 100BT with pass-through for 10BT. Example cards come from DEC
+ (MicroLinear ML6694 PHY) and Znyx (Kendin KS8761 PHY). There is no
+ support for MII or AUI interfaces.
+
+ This SB1250 version takes advantage of DMA coherence and uses
+ "preserve bit lanes" addresses for all accesses that cross the
+ ZBbus-PCI bridge. */
+
+#ifndef TULIP_DEBUG
+#define TULIP_DEBUG 0
+#endif
+
+#ifndef TULIP_TUNE
+#define TULIP_TUNE 1
+#endif
+
+#define ENET_ADDR_LEN 6 /* size of an ethernet address */
+#define MAX_ETHER_PACK 1518 /* max size of a packet */
+#define CRC_SIZE 4 /* size of CRC field */
+
+/* The following must be a multiple of 4. In late versions of the
+ tulip, the rx DMA engine also apparently writes beyond 1520 bytes
+ for received packets > 1516 bytes (WriteInvalidate only?). */
+#define ETH_BUFFER_SIZE 1536
+
+typedef struct eth_pkt_s {
+ queue_t next;
+ void *devctx;
+ unsigned char *buffer;
+ unsigned int flags;
+ int length;
+ /* packet data goes here, should always be longword aligned */
+} eth_pkt_t;
+
+/* packet flags */
+#define ETH_TX_SETUP 1
+
+static void
+show_packet(eth_pkt_t *pkt)
+{
+ int i;
+ int n = (pkt->length < 32 ? pkt->length : 32);
+
+ xprintf("[%4d]:", pkt->length);
+ for (i = 0; i < n; i++) {
+ if (i % 4 == 0)
+ xprintf(" ");
+ xprintf("%02x", pkt->buffer[i]);
+ }
+ xprintf("\n");
+}
+
+
+/* Descriptor structures */
+
+typedef struct rx_dscr {
+ uint32_t rxd_flags;
+ uint32_t rxd_bufsize;
+ uint32_t rxd_bufaddr1;
+ uint32_t rxd_bufaddr2;
+} rx_dscr;
+
+typedef struct tx_dscr {
+ uint32_t txd_flags;
+ uint32_t txd_bufsize;
+ uint32_t txd_bufaddr1;
+ uint32_t txd_bufaddr2;
+} tx_dscr;
+
+/* CAM structure */
+
+typedef union {
+ struct {
+ uint32_t physical[CAM_PERFECT_ENTRIES][3];
+ } p;
+ struct {
+ uint32_t hash[32];
+ uint32_t mbz[7];
+ uint32_t physical[3];
+ } h;
+} tulip_cam;
+
+
+typedef enum {
+ eth_state_uninit,
+ eth_state_setup,
+ eth_state_off,
+ eth_state_on,
+ eth_state_broken
+} eth_state_t;
+
+#define ETH_PKTPOOL_SIZE 20
+#define ETH_PKTBUF_SIZE (sizeof(eth_pkt_t) + ((ETH_BUFFER_SIZE+7)&~7))
+
+typedef struct tulip_softc {
+ uint32_t membase;
+ uint8_t irq; /* interrupt mapping (not currently used) */
+ pcitag_t tag; /* tag for configuration registers */
+
+ uint8_t hwaddr[ENET_ADDR_LEN];
+ uint16_t device; /* chip device code */
+ uint8_t revision; /* chip revision and step (Table 3-7) */
+
+ /* current state */
+ eth_state_t state;
+ int bus_errors;
+
+ /* These fields are the chip startup values. */
+// uint16_t media; /* media type */
+ uint32_t opmode; /* operating mode */
+ uint32_t intmask; /* interrupt mask */
+
+ /* This field is set before calling dc2114x_hwinit */
+ int linkspeed; /* encoding from cfe_ioctl */
+
+ /* Packet free list */
+ queue_t freelist;
+ uint8_t *pktpool;
+ queue_t rxqueue;
+
+ /* The descriptor tables */
+ uint8_t *rxdscrmem; /* receive descriptors */
+ uint8_t *txdscrmem; /* transmit descriptors */
+
+ eth_pkt_t **rxdscrinfo;
+ eth_pkt_t **txdscrinfo;
+
+ /* These fields keep track of where we are in tx/rx processing */
+ volatile rx_dscr *rxdscr_start; /* beginning of ring */
+ volatile rx_dscr *rxdscr_end; /* end of ring */
+ volatile rx_dscr *rxdscr_remove; /* next one we expect tulip to use */
+ volatile rx_dscr *rxdscr_add; /* next place to put a buffer */
+ int rxdscr_onring;
+
+ volatile tx_dscr *txdscr_start; /* beginning of ring */
+ volatile tx_dscr *txdscr_end; /* end of ring */
+ volatile tx_dscr *txdscr_remove; /* next one we will use for tx */
+ volatile tx_dscr *txdscr_add; /* next place to put a buffer */
+
+ /* These fields describe the PHY */
+ int mii_addr;
+
+} tulip_softc;
+
+
+/* Driver parameterization */
+
+#define MAXRXDSCR 16
+#define MAXTXDSCR 16
+#define MINRXRING 8
+
+#define MEDIA_UNKNOWN 0
+#define MEDIA_AUI 1
+#define MEDIA_BNC 2
+#define MEDIA_UTP_FULL_DUPLEX 3
+#define MEDIA_UTP_NO_LINK_TEST 4
+#define MEDIA_UTP 5
+
+/* Prototypes */
+
+static void tulip_ether_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+
+/* Address mapping macros */
+
+/* Note that PHYSADDR only works with 32-bit addresses, but the
+ so does the Tulip. */
+#define PHYSADDR(sc,x) (K0_TO_PHYS((uintptr_t)(x)))
+
+#define PCIADDR(a,b) ((uint32_t) (b))
+#define PCIADDRX(a,b) ((uint32_t) (b) | 0x20000000)
+#define PCI_TO_CPU(a) (a)
+
+#if __long64
+#define READCSR(sc,csr) \
+ (*((volatile uint32_t *) \
+ (PHYS_TO_XKSEG_UNCACHED(PCI_TO_CPU((sc)->membase)+(csr)))))
+
+#define WRITECSR(sc,csr,val) \
+ (*((volatile uint32_t *) \
+ (PHYS_TO_XKSEG_UNCACHED(PCI_TO_CPU((sc)->membase)+(csr)))) = (val))
+
+#else
+#define READCSR(sc,csr) \
+ (hs_read32(PHYS_TO_XKSEG_UNCACHED(PCI_TO_CPU((sc)->membase)+(csr))))
+
+#define WRITECSR(sc,csr,val) \
+ (hs_write32(PHYS_TO_XKSEG_UNCACHED(PCI_TO_CPU((sc)->membase)+(csr)), \
+ (val)))
+
+#endif
+
+
+#define RESET_ADAPTER(sc) \
+ { \
+ WRITECSR((sc), R_CSR_BUSMODE, M_CSR0_SWRESET); \
+ cfe_sleep(CFE_HZ/10); \
+ }
+
+
+/* Debugging */
+
+static void
+dumpstat(tulip_softc *sc)
+{
+ xprintf("-- CSR 5 = %08X CSR 6 = %08x\n",
+ READCSR(sc, R_CSR_STATUS), READCSR(sc, R_CSR_OPMODE));
+}
+
+static void
+dumpcsrs(tulip_softc *sc)
+{
+ int idx;
+
+ xprintf("-------------\n");
+ for (idx = 0; idx < 16; idx++) {
+ xprintf("CSR %2d = %08X\n", idx, READCSR(sc, idx*8));
+ }
+ xprintf("-------------\n");
+}
+
+
+/* Packet management */
+
+/* *********************************************************************
+ * ETH_ALLOC_PKT(s)
+ *
+ * Allocate a packet from the free list.
+ *
+ * Input parameters:
+ * s - eth structure
+ *
+ * Return value:
+ * pointer to packet structure, or NULL if none available
+ ********************************************************************* */
+#define ETHPKT_ALIGN ((uintptr_t) 4)
+
+static eth_pkt_t *
+eth_alloc_pkt(tulip_softc *s)
+{
+ uintptr_t addr;
+ eth_pkt_t *pkt;
+
+ pkt = (eth_pkt_t *) q_deqnext(&s->freelist);
+ if (!pkt) return NULL;
+
+ addr = (uintptr_t) (pkt+1);
+ if (addr & (ETHPKT_ALIGN-1)) {
+ addr = (addr + ETHPKT_ALIGN) & ~(ETHPKT_ALIGN-1);
+ }
+
+ pkt->buffer = (uint8_t *) addr;
+ pkt->length = ETH_BUFFER_SIZE;
+ pkt->flags = 0;
+
+ return pkt;
+}
+
+
+/* *********************************************************************
+ * ETH_FREE_PKT(s,pkt)
+ *
+ * Return a packet to the free list
+ *
+ * Input parameters:
+ * s - sbmac structure
+ * pkt - packet to return
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void
+eth_free_pkt(tulip_softc *s, eth_pkt_t *pkt)
+{
+ q_enqueue(&s->freelist, &pkt->next);
+}
+
+
+/* *********************************************************************
+ * ETH_INITFREELIST(s)
+ *
+ * Initialize the buffer free list for this mac. The memory
+ * allocated to the free list is carved up and placed on a linked
+ * list of buffers for use by the mac.
+ *
+ * Input parameters:
+ * s - eth structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void
+eth_initfreelist(tulip_softc *s)
+{
+ int idx;
+ unsigned char *ptr;
+ eth_pkt_t *pkt;
+
+ q_init(&s->freelist);
+
+ ptr = s->pktpool;
+ for (idx = 0; idx < ETH_PKTPOOL_SIZE; idx++) {
+ pkt = (eth_pkt_t *) ptr;
+ eth_free_pkt(s, pkt);
+ ptr += ETH_PKTBUF_SIZE;
+ }
+}
+
+
+/* Descriptor ring management */
+
+static int
+tulip_add_rcvbuf(tulip_softc *sc, eth_pkt_t *pkt)
+{
+ volatile rx_dscr *rxd;
+ volatile rx_dscr *nextrxd;
+ int idx;
+ uint32_t flags = 0;
+
+ rxd = sc->rxdscr_add;
+
+ /* Figure out where the next descriptor will go */
+ nextrxd = rxd+1;
+ if (nextrxd == sc->rxdscr_end) {
+ nextrxd = sc->rxdscr_start;
+ flags = M_RDES1_ENDOFRING;
+ }
+
+ /*
+ * If the next one is the same as our remove pointer,
+ * the ring is considered full. (it actually has room for
+ * one more, but we reserve the remove == add case for "empty")
+ */
+ if (nextrxd == sc->rxdscr_remove) return -1;
+
+ /* Save this packet pointer. */
+ idx = rxd - sc->rxdscr_start;
+ sc->rxdscrinfo[idx] = pkt;
+
+ rxd->rxd_bufsize = V_RDES1_BUF1SIZE(ETH_BUFFER_SIZE) | flags;
+ rxd->rxd_bufaddr1 = PCIADDRX(sc, PHYSADDR(sc, pkt->buffer));
+ rxd->rxd_bufaddr2 = 0;
+ rxd->rxd_flags = M_RDES0_OWNADAP;
+
+ /* success, advance the pointer */
+ sc->rxdscr_add = nextrxd;
+ sc->rxdscr_onring++;
+
+ return 0;
+}
+
+static void
+tulip_fillrxring(tulip_softc *sc)
+{
+ eth_pkt_t *pkt;
+
+ while (sc->rxdscr_onring < MINRXRING) {
+ pkt = eth_alloc_pkt(sc);
+ if (pkt == NULL) {
+ /* could not allocate a buffer */
+ break;
+ }
+ if (tulip_add_rcvbuf(sc, pkt) != 0) {
+ /* could not add buffer to ring */
+ eth_free_pkt(sc, pkt);
+ break;
+ }
+ }
+}
+
+
+/* *********************************************************************
+ * TULIP_RX_CALLBACK(sc, pkt)
+ *
+ * Receive callback routine. This routine is invoked when a
+ * buffer queued for receives is filled. In this simple driver,
+ * all we do is add the packet to a per-MAC queue for later
+ * processing, and try to put a new packet in the place of the one
+ * that was removed from the queue.
+ *
+ * Input parameters:
+ * sc - interface
+ * ptk - packet context (sbeth_pkt structure)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void
+tulip_rx_callback(tulip_softc *sc, eth_pkt_t *pkt)
+{
+ if (TULIP_DEBUG) show_packet(pkt); /* debug */
+
+ q_enqueue(&sc->rxqueue, &pkt->next);
+
+ tulip_fillrxring(sc);
+}
+
+
+static void
+tulip_procrxring(tulip_softc *sc)
+{
+ volatile rx_dscr *rxd;
+ eth_pkt_t *pkt;
+ eth_pkt_t *newpkt;
+ int idx;
+ uint32_t flags;
+
+ for (;;) {
+ rxd = (volatile rx_dscr *) sc->rxdscr_remove;
+ idx = rxd - sc->rxdscr_start;
+
+ flags = rxd->rxd_flags;
+
+ if (flags & M_RDES0_OWNADAP) {
+ /* end of ring, no more packets */
+ break;
+ }
+
+ pkt = sc->rxdscrinfo[idx];
+
+ /* Drop error packets */
+ if (flags & M_RDES0_ERRORSUM) {
+ xprintf("DC2114x: rx error %04X\n", flags & 0xFFFF);
+ tulip_add_rcvbuf(sc, pkt);
+ goto next;
+ }
+
+ /* Pass up the packet */
+ pkt->length = G_RDES0_FRAMELEN(flags) - CRC_SIZE;
+ tulip_rx_callback(sc, pkt);
+
+ /* put a buffer back on the ring to replace this one */
+ newpkt = eth_alloc_pkt(sc);
+ if (newpkt) tulip_add_rcvbuf(sc, newpkt);
+
+next:
+ /* update the pointer, accounting for buffer wrap. */
+ rxd++;
+ if (rxd == sc->rxdscr_end)
+ rxd = sc->rxdscr_start;
+
+ sc->rxdscr_remove = (rx_dscr *) rxd;
+ sc->rxdscr_onring--;
+ }
+}
+
+
+static int
+tulip_add_txbuf(tulip_softc *sc, eth_pkt_t *pkt)
+{
+ volatile tx_dscr *txd;
+ volatile tx_dscr *nexttxd;
+ int idx;
+ uint32_t bufsize = 0;
+
+ txd = sc->txdscr_add;
+
+ /* Figure out where the next descriptor will go */
+ nexttxd = (txd+1);
+ if (nexttxd == sc->txdscr_end) {
+ nexttxd = sc->txdscr_start;
+ bufsize = M_TDES1_ENDOFRING;
+ }
+
+ /* If the next one is the same as our remove pointer,
+ the ring is considered full. (it actually has room for
+ one more, but we reserve the remove == add case for "empty") */
+
+ if (nexttxd == sc->txdscr_remove) return -1;
+
+ /* Save this packet pointer. */
+ idx = txd - sc->txdscr_start;
+ sc->txdscrinfo[idx] = pkt;
+
+ bufsize |= V_TDES1_BUF1SIZE(pkt->length) |
+ M_TDES1_FIRSTSEG | M_TDES1_LASTSEG | M_TDES1_INTERRUPT;
+ if (pkt->flags & ETH_TX_SETUP) {
+ /* For a setup packet, FIRSTSEG and LASTSEG should be clear (!) */
+ bufsize ^= M_TDES1_SETUP | M_TDES1_FIRSTSEG | M_TDES1_LASTSEG;
+ }
+ txd->txd_bufsize = bufsize;
+ txd->txd_bufaddr1 = PCIADDRX(sc, PHYSADDR(sc, pkt->buffer));
+ txd->txd_bufaddr2 = 0;
+ txd->txd_flags = M_TDES0_OWNADAP;
+
+ /* success, advance the pointer */
+ sc->txdscr_add = nexttxd;
+
+ return 0;
+}
+
+
+static int
+tulip_transmit(tulip_softc *sc,eth_pkt_t *pkt)
+{
+ tulip_add_txbuf(sc, pkt);
+
+ WRITECSR(sc, R_CSR_TXPOLL, 1);
+ return 0;
+}
+
+
+static void
+tulip_proctxring(tulip_softc *sc)
+{
+ volatile tx_dscr *txd;
+ eth_pkt_t *pkt;
+ int idx;
+ uint32_t flags;
+
+ for (;;) {
+ txd = (volatile tx_dscr *) sc->txdscr_remove;
+ idx = txd - sc->txdscr_start;
+
+ flags = txd->txd_flags;
+
+ if (txd == sc->txdscr_add) {
+ /* ring is empty, no buffers to process */
+ break;
+ }
+
+ if (flags & M_RDES0_OWNADAP) {
+ /* Reached a packet still being transmitted */
+ break;
+ }
+
+ /* Check for a completed setup packet */
+ pkt = sc->txdscrinfo[idx];
+ if (pkt->flags & ETH_TX_SETUP) {
+ if (sc->state == eth_state_setup) {
+ /* check flag bits */
+ sc->state = eth_state_on;
+ }
+ pkt->flags &=~ ETH_TX_SETUP;
+ }
+
+ /* Just free the packet */
+ eth_free_pkt(sc, pkt);
+
+ /* update the pointer, accounting for buffer wrap. */
+ txd++;
+ if (txd == sc->txdscr_end)
+ txd = sc->txdscr_start;
+
+ sc->txdscr_remove = (tx_dscr *) txd;
+ }
+}
+
+
+static void
+tulip_initrings(tulip_softc *sc)
+{
+ volatile tx_dscr *txd;
+ volatile rx_dscr *rxd;
+
+ /* Claim ownership of all transmit descriptors */
+
+ for (txd = sc->txdscr_start; txd != sc->txdscr_end; txd++)
+ txd->txd_flags = 0;
+ for (rxd = sc->rxdscr_start; rxd != sc->rxdscr_end; rxd++)
+ rxd->rxd_flags = 0;
+
+ /* Init the ring pointers */
+
+ sc->txdscr_add = sc->txdscr_remove = sc->txdscr_start;
+ sc->rxdscr_add = sc->rxdscr_remove = sc->rxdscr_start;
+ sc->rxdscr_onring = 0;
+
+ /* Add stuff to the receive ring */
+
+ tulip_fillrxring(sc);
+}
+
+
+static int
+tulip_init(tulip_softc *sc)
+{
+ /* Allocate descriptor rings and lookaside lists */
+ sc->rxdscrmem = KMALLOC(MAXRXDSCR*sizeof(rx_dscr),sizeof(rx_dscr));
+ sc->txdscrmem = KMALLOC(MAXTXDSCR*sizeof(tx_dscr),sizeof(tx_dscr));
+ sc->rxdscrinfo = KMALLOC(MAXRXDSCR*sizeof(eth_pkt_t *),sizeof(eth_pkt_t));
+ sc->txdscrinfo = KMALLOC(MAXTXDSCR*sizeof(eth_pkt_t *),sizeof(eth_pkt_t));
+
+ /* Allocate buffer pool */
+ sc->pktpool = KMALLOC(ETH_PKTPOOL_SIZE*ETH_PKTBUF_SIZE, 0);
+ eth_initfreelist(sc);
+ q_init(&sc->rxqueue);
+
+ /* Fill in pointers to the rings */
+ sc->rxdscr_start = (rx_dscr *) (sc->rxdscrmem);
+ sc->rxdscr_end = sc->rxdscr_start + MAXRXDSCR;
+ sc->rxdscr_add = sc->rxdscr_start;
+ sc->rxdscr_remove = sc->rxdscr_start;
+ sc->rxdscr_onring = 0;
+
+ sc->txdscr_start = (tx_dscr *) (sc->txdscrmem);
+ sc->txdscr_end = sc->txdscr_start + MAXTXDSCR;
+ sc->txdscr_add = sc->txdscr_start;
+ sc->txdscr_remove = sc->txdscr_start;
+
+ tulip_initrings(sc);
+
+ return 0;
+}
+
+
+static void
+tulip_resetrings(tulip_softc *sc)
+{
+ volatile tx_dscr *txd;
+ volatile rx_dscr *rxd;
+ int idx;
+
+ /* Free already-sent descriptors and buffers */
+ tulip_proctxring(sc);
+
+ /* Free any pending but unsent */
+ txd = (volatile tx_dscr *) sc->txdscr_remove;
+ while (txd != sc->txdscr_add) {
+ idx = txd - sc->txdscr_start;
+ eth_free_pkt(sc, sc->txdscrinfo[idx]);
+ txd->txd_flags &=~ M_TDES0_OWNADAP;
+
+ txd++;
+ if (txd == sc->txdscr_end)
+ txd = sc->txdscr_start;
+ }
+ sc->txdscr_add = sc->txdscr_remove;
+
+ /* Discard any received packets as well as all free buffers */
+ rxd = (volatile rx_dscr *) sc->rxdscr_remove;
+ while (rxd != sc->rxdscr_add) {
+ idx = rxd - sc->rxdscr_start;
+ eth_free_pkt(sc, sc->rxdscrinfo[idx]);
+ rxd->rxd_flags &=~ M_RDES0_OWNADAP;
+
+ rxd++;
+ if (rxd == sc->rxdscr_end)
+ rxd = sc->rxdscr_start;
+ sc->rxdscr_onring--;
+ }
+
+ /* Reestablish the initial state. */
+ tulip_initrings(sc);
+}
+
+
+/* CRCs */
+
+#define IEEE_CRC32_POLY 0xEDB88320UL /* CRC-32 Poly -- either endian */
+
+static uint32_t
+tulip_crc32(const uint8_t *databuf, unsigned int datalen)
+{
+ unsigned int idx, bit, data;
+ uint32_t crc;
+
+ crc = 0xFFFFFFFFUL;
+ for (idx = 0; idx < datalen; idx++)
+ for (data = *databuf++, bit = 0; bit < 8; bit++, data >>= 1)
+ crc = (crc >> 1) ^ (((crc ^ data) & 1) ? IEEE_CRC32_POLY : 0);
+ return crc;
+}
+
+#define tulip_mchash(mca) (tulip_crc32((mca), 6) & 0x1FF)
+
+
+/* Serial ROM access */
+
+/****************************************************************************
+ * tulip_spin(sc, ns)
+ *
+ * Spin for a short interval (nominally in nanoseconds)
+ *
+ * Input Parameters: ns - minimum required nsec.
+ *
+ * The delay loop uses uncached PCI reads, each of which requires
+ * at least 3 PCI bus clocks (45 ns at 66 MHz) to complete. The
+ * actual delay will be longer (much longer if preempted).
+ ***************************************************************************/
+
+#define PCI_MIN_DELAY 45
+
+static void
+tulip_spin(tulip_softc *sc, long nanoseconds)
+{
+ long delay;
+ volatile uint32_t t;
+
+ for (delay = nanoseconds; delay > 0; delay -= PCI_MIN_DELAY)
+ t = READCSR(sc, R_CSR_BUSMODE);
+}
+
+
+/*
+ * Delays below are chosen to meet specs for NS93C64 (slow M variant).
+ * Current parts are faster.
+ * Reference: NS Memory Data Book, 1994
+ */
+
+#define SROM_SIZE 128
+#define SROM_MAX_CYCLES 32
+
+#define SROM_CMD_BITS 3
+#define SROM_ADDR_BITS 6
+
+#define K_SROM_READ_CMD 06
+#define K_SROM_WRITE_CMD 05
+
+#define SROM_ADDR_OFFSET 0x14
+#define SROM_CRC_OFFSET (SROM_SIZE-2)
+
+
+static void
+srom_idle_state(tulip_softc *sc)
+{
+ uint32_t csr9;
+ unsigned int i;
+
+ csr9 = READCSR(sc, R_CSR_ROM_MII);
+
+ csr9 |= M_CSR9_SROMCHIPSEL;
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 100); /* CS setup (Tcss=100) */
+
+ /* Run the clock through the maximum number of pending read cycles */
+ for (i = 0; i < SROM_MAX_CYCLES*2; i++) {
+ csr9 ^= M_CSR9_SROMCLOCK;
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 1000); /* SK period (Fsk=0.5MHz) */
+ }
+
+ /* Deassert SROM Chip Select */
+ csr9 &=~ M_CSR9_SROMCHIPSEL;
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 50); /* CS recovery (Tsks=50) */
+}
+
+static void
+srom_send_command_bit(tulip_softc *sc, unsigned int data)
+{
+ uint32_t csr9;
+
+ csr9 = READCSR(sc, R_CSR_ROM_MII);
+
+ /* Place the data bit on the bus */
+ if (data == 1)
+ csr9 |= M_CSR9_SROMDATAIN;
+ else
+ csr9 &=~ M_CSR9_SROMDATAIN;
+
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 360); /* setup: Tdis=200 */
+
+ /* Now clock the data into the SROM */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9 | M_CSR9_SROMCLOCK);
+ tulip_spin(sc, 900); /* clock high, Tskh=500 */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 450); /* clock low, Tskl=250 */
+
+ /* Now clear the data bit */
+ csr9 &=~ M_CSR9_SROMDATAIN; /* data invalid, Tidh=20 for SK^ */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 270); /* min cycle, 1/Fsk=2000 */
+}
+
+static uint16_t
+srom_read_bit(tulip_softc *sc)
+{
+ uint32_t csr9;
+
+ csr9 = READCSR(sc, R_CSR_ROM_MII);
+
+ /* Generate a clock cycle before doing a read */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9 | M_CSR9_SROMCLOCK); /* rising edge */
+ tulip_spin(sc, 1000); /* clock high, Tskh=500, Tpd=1000 */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9); /* falling edge */
+ tulip_spin(sc, 1000); /* clock low, 1/Fsk=2000 */
+
+ csr9 = READCSR(sc, R_CSR_ROM_MII);
+ return ((csr9 & M_CSR9_SROMDATAOUT) != 0 ? 1 : 0);
+}
+
+#define CMD_BIT_MASK (1 << (SROM_CMD_BITS+SROM_ADDR_BITS-1))
+
+static uint16_t
+srom_read_word(tulip_softc *sc, unsigned int index)
+{
+ uint16_t command, word;
+ uint32_t csr9;
+ unsigned int i;
+
+ csr9 = READCSR(sc, R_CSR_ROM_MII) | M_CSR9_SROMCHIPSEL;
+
+ /* Assert the SROM CS line */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 100); /* CS setup, Tcss = 100 */
+
+ /* Send the read command to the SROM */
+ command = (K_SROM_READ_CMD << SROM_ADDR_BITS) | index;
+ for (i = 0; i < SROM_CMD_BITS+SROM_ADDR_BITS; i++) {
+ srom_send_command_bit(sc, (command & CMD_BIT_MASK) != 0 ? 1 : 0);
+ command <<= 1;
+ }
+
+ /* Now read the bits from the SROM (MSB first) */
+ word = 0;
+ for (i = 0; i < 16; ++i) {
+ word <<= 1;
+ word |= srom_read_bit(sc);
+ }
+
+ /* Clear the SROM CS Line, CS hold, Tcsh = 0 */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9 &~ M_CSR9_SROMCHIPSEL);
+
+ return word;
+}
+
+
+/****************************************************************************
+ * srom_calc_crc()
+ *
+ * Calculate the CRC of the SROM and return it. We compute the
+ * CRC per Appendix A of the 21140A ROM/external register data
+ * sheet (EC-QPQWA-TE).
+ ***************************************************************************/
+
+static uint16_t
+srom_calc_crc(tulip_softc *sc, uint8_t srom[], int length)
+{
+ uint32_t crc = tulip_crc32(srom, length) ^ 0xffffffff;
+
+ return (uint16_t)(crc & 0xffff);
+}
+
+/****************************************************************************
+ * srom_read_all(sc, uint8_t dest)
+ *
+ * Read the entire SROM into the srom array
+ *
+ * Input parameters:
+ * sc - tulip state
+ ***************************************************************************/
+
+#define STORED_CRC(rom) \
+ ((rom)[SROM_CRC_OFFSET] | ((rom)[SROM_CRC_OFFSET+1] << 8))
+
+static int
+srom_read_all(tulip_softc *sc, uint8_t dest[])
+{
+ int i;
+ uint16_t crc, temp;
+
+ WRITECSR(sc, R_CSR_ROM_MII, M_CSR9_SERROMSEL|M_CSR9_ROMREAD);
+
+ srom_idle_state(sc);
+
+ for (i = 0; i < SROM_SIZE/2; i++) {
+ temp = srom_read_word(sc, i);
+ dest[2*i] = temp & 0xff;
+ dest[2*i+1] =temp >> 8;
+ }
+
+ WRITECSR(sc, R_CSR_ROM_MII, 0); /* CS hold, Tcsh=0 */
+
+ crc = srom_calc_crc(sc, dest, SROM_CRC_OFFSET);
+ if (crc != STORED_CRC(dest)) {
+ crc = srom_calc_crc(sc, dest, 94); /* "alternative" */
+ if (crc != STORED_CRC(dest)) {
+ xprintf("DC2114x: Invalid SROM CRC, calc %04x, stored %04x\n",
+ crc, STORED_CRC(dest));
+ return 0/*-1*/;
+ }
+ }
+ return 0;
+}
+
+static int
+srom_read_addr(tulip_softc *sc, uint8_t buf[])
+{
+ uint8_t srom[SROM_SIZE];
+
+ if (srom_read_all(sc, srom) == 0) {
+ memcpy(buf, &srom[SROM_ADDR_OFFSET], ENET_ADDR_LEN);
+ return 0;
+ }
+
+ return -1;
+}
+
+
+/****************************************************************************
+ * MII access utility routines
+ ***************************************************************************/
+
+/* MII clock limited to 2.5 MHz, transactions end with MDIO tristated */
+
+static void
+mii_write_bits(tulip_softc *sc, uint32_t data, unsigned int count)
+{
+ uint32_t csr9;
+ uint32_t bitmask;
+
+ csr9 = READCSR(sc, R_CSR_ROM_MII) &~ (M_CSR9_MDC | M_CSR9_MIIMODE);
+
+ for (bitmask = 1 << (count-1); bitmask != 0; bitmask >>= 1) {
+ csr9 &=~ M_CSR9_MDO;
+ if ((data & bitmask) != 0) csr9 |= M_CSR9_MDO;
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+
+ tulip_spin(sc, 2000); /* setup */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9 | M_CSR9_MDC);
+ tulip_spin(sc, 2000); /* hold */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ }
+}
+
+static void
+mii_turnaround(tulip_softc *sc)
+{
+ uint32_t csr9;
+
+ csr9 = READCSR(sc, R_CSR_ROM_MII) | M_CSR9_MIIMODE;
+
+ /* stop driving data */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 2000); /* setup */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9 | M_CSR9_MDC);
+ tulip_spin(sc, 2000); /* clock high */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+
+ /* read back and check for 0 here? */
+}
+
+/****************************************************************************
+ * mii_read_register
+ *
+ * This routine reads a register from the PHY chip using the MII
+ * serial management interface.
+ *
+ * Input parameters:
+ * index - index of register to read (0-31)
+ *
+ * Return value:
+ * word read from register
+ ***************************************************************************/
+
+static uint16_t
+mii_read_register(tulip_softc *sc, unsigned int index)
+{
+ /* Send the command and address to the PHY. The sequence is
+ a synchronization sequence (32 1 bits)
+ a "start" command (2 bits)
+ a "read" command (2 bits)
+ the PHY addr (5 bits)
+ the register index (5 bits)
+ */
+ uint32_t csr9;
+ uint16_t word;
+ int i;
+
+ mii_write_bits(sc, 0xff, 8);
+ mii_write_bits(sc, 0xffffffff, 32);
+ mii_write_bits(sc, MII_COMMAND_START, 2);
+ mii_write_bits(sc, MII_COMMAND_READ, 2);
+ mii_write_bits(sc, sc->mii_addr /* XXX sc->phy.index */, 5);
+ mii_write_bits(sc, index, 5);
+
+ mii_turnaround(sc);
+
+ csr9 = (READCSR(sc, R_CSR_ROM_MII) &~ M_CSR9_MDC) | M_CSR9_MIIMODE;
+ word = 0;
+
+ for (i = 0; i < 16; i++) {
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 2000); /* clock width low */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9 | M_CSR9_MDC);
+ tulip_spin(sc, 2000); /* clock width high */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 1000); /* output delay */
+ word <<= 1;
+ if ((READCSR(sc, R_CSR_ROM_MII) & M_CSR9_MDI) != 0)
+ word |= 0x0001;
+ }
+
+ return word;
+
+ /* reset to output mode? */
+}
+
+/****************************************************************************
+ * mii_write_register
+ *
+ * This routine writes a register in the PHY chip using the MII
+ * serial management interface.
+ *
+ * Input parameters:
+ * index - index of register to write (0-31)
+ * value - word to write
+ ***************************************************************************/
+
+static void
+mii_write_register(tulip_softc *sc, unsigned int index, uint16_t value)
+{
+ mii_write_bits(sc, 0xff, 8);
+ mii_write_bits(sc, 0xffffffff, 32);
+ mii_write_bits(sc, MII_COMMAND_START, 2);
+ mii_write_bits(sc, MII_COMMAND_WRITE, 2);
+ mii_write_bits(sc, sc->mii_addr /* XXX sc->phy.index */, 5);
+ mii_write_bits(sc, index, 5);
+ mii_write_bits(sc, MII_COMMAND_ACK, 2);
+ mii_write_bits(sc, value, 16);
+
+ /* reset to input mode? */
+}
+
+
+static int
+mii_probe(tulip_softc *sc)
+{
+ int i;
+ uint16_t id1, id2;
+
+ for (i = 0; i < 32; i++) {
+ sc->mii_addr = i;
+ id1 = mii_read_register(sc, MII_PHYIDR1);
+ id2 = mii_read_register(sc, MII_PHYIDR2);
+ if ((id1 != 0xffff || id2 != 0xffff) &&
+ (id1 != 0x0000 || id2 != 0x0000)) {
+ return 0;
+ }
+ }
+ return -1;
+}
+
+#if 0
+static void
+mii_dump(tulip_softc *sc)
+{
+ int i;
+ uint16_t r;
+
+ for (i = 0; i <=6; ++i) {
+ r = mii_read_register(sc, i);
+ if (r != 0) xprintf("MII_REG%02x: %04x\n", i, r);
+ }
+ for (i = 21; i <= 25; ++i) {
+ r = mii_read_register(sc, i);
+ if (r != 0) printf("MII_REG%02x: %04x\n", i, r);
+ }
+}
+#else
+#define mii_dump(sc)
+#endif
+
+
+#if 0
+static void
+tulip_getaddr(tulip_softc *sc, uint8_t *buf)
+{
+ memcpy(buf, sc->hwaddr, ENET_ADDR_LEN);
+}
+#endif
+
+
+/* Chip specific code */
+
+static void
+dc21143_set_speed(tulip_softc *sc, int speed)
+{
+ uint32_t opmode = 0;
+
+ WRITECSR(sc, R_CSR_SIAMODE0, 0);
+
+ switch (speed) {
+ case ETHER_SPEED_AUTO:
+ break;
+ case ETHER_SPEED_10HDX:
+ default:
+ WRITECSR(sc, R_CSR_SIAMODE1, M_CSR14_10BT_HD);
+ WRITECSR(sc, R_CSR_SIAMODE2, M_CSR15_DEFAULT_VALUE);
+ opmode = M_CSR6_SPEED_10;
+ break;
+ case ETHER_SPEED_10FDX:
+ WRITECSR(sc, R_CSR_SIAMODE1, M_CSR14_10BT_FD);
+ WRITECSR(sc, R_CSR_SIAMODE2, M_CSR15_DEFAULT_VALUE);
+ opmode = M_CSR6_SPEED_10 | M_CSR6_FULLDUPLEX;
+ break;
+ case ETHER_SPEED_100HDX:
+ WRITECSR(sc, R_CSR_SIAMODE1, 0);
+ WRITECSR(sc, R_CSR_SIAMODE2, M_CSR15_DEFAULT_VALUE);
+ opmode = M_CSR6_SPEED_100;
+ break;
+ case ETHER_SPEED_100FDX:
+ WRITECSR(sc, R_CSR_SIAMODE1, 0);
+ WRITECSR(sc, R_CSR_SIAMODE2, M_CSR15_DEFAULT_VALUE);
+ opmode = M_CSR6_SPEED_100 | M_CSR6_FULLDUPLEX;
+ break;
+ }
+
+ WRITECSR(sc, R_CSR_SIAMODE0, M_CSR13_CONN_NOT_RESET);
+
+ opmode |= M_CSR6_MBO;
+#if TULIP_TUNE
+ opmode |= V_CSR6_THRESHCONTROL(K_CSR6_TXTHRES_128_72);
+#else
+ opmode |= M_CSR6_STOREFWD;
+#endif
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+}
+
+static void
+dc21143_autonegotiate(tulip_softc *sc)
+{
+ uint32_t opmode;
+ uint32_t tempword;
+ int count;
+ int linkspeed;
+
+ linkspeed = ETHER_SPEED_UNKNOWN;
+
+ /* Program the media setup into the CSRs. */
+ /* reset SIA */
+ WRITECSR(sc, R_CSR_SIAMODE0, 0);
+
+ /* set to speed_10, fullduplex to start_nway */
+ opmode =
+ M_CSR6_SPEED_10 |
+ M_CSR6_FULLDUPLEX |
+ M_CSR6_MBO;
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+
+ /* Choose advertised capabilities */
+ tempword =
+ M_CSR14_100BASETHALFDUP |
+ M_CSR14_100BASETFULLDUP |
+ M_CSR14_HALFDUPLEX10BASET;
+ WRITECSR(sc, R_CSR_SIAMODE1, tempword);
+
+ /* Enable autonegotiation */
+ tempword |= M_CSR14_AUTONEGOTIATE | 0xffff;
+ WRITECSR(sc, R_CSR_SIAMODE1, tempword);
+ WRITECSR(sc, R_CSR_SIAMODE2, M_CSR15_DEFAULT_VALUE);
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+ WRITECSR(sc, R_CSR_SIAMODE0, M_CSR13_CONN_NOT_RESET);
+
+ /* STATE check nway, poll until a valid 10/100mbs signal seen */
+ WRITECSR(sc, R_CSR_STATUS, M_CSR5_LINKPASS); /* try to clear this... */
+
+ /* (Re)start negotiation */
+ tempword = READCSR(sc, R_CSR_SIASTATUS);
+ tempword &=~ M_CSR12_AUTONEGARBIT;
+ tempword |= V_CSR12_AUTONEGARBIT(0x1);
+
+ for (count = 0; count <= 130; count++) {
+ tempword = READCSR(sc, R_CSR_STATUS);
+ if (tempword & M_CSR5_LINKPASS)
+ break;
+ cfe_sleep(CFE_HZ/100);
+ }
+
+ if (count > 130)
+ xprintf("DC21143: Link autonegotiation failed\n");
+
+ /* STATE configure nway, check to see if any abilities common to us.
+ If they do, set to highest mode, if not, we will see if the partner
+ will do 100mb or 10mb - then set it */
+
+ tempword = READCSR(sc, R_CSR_SIASTATUS);
+ /* clear the autonegogiate complete bit */
+ WRITECSR(sc, R_CSR_STATUS, M_CSR5_LINKPASS);
+
+ if (tempword & M_CSR12_LINKPARTNEG) {
+ /* A link partner was negogiated... */
+
+ xprintf("DC21143: Negotiated ");
+ if (tempword & 0x01000000) { /* 100FD */
+ xprintf("100Mb/s FDX");
+ linkspeed = ETHER_SPEED_100FDX;
+ }
+ else if (tempword & 0x00800000) { /* 100HD */
+ xprintf("100Mb/s HDX");
+ linkspeed = ETHER_SPEED_100HDX;
+ }
+ else if (tempword & 0x00400000) { /* 10FD */
+ xprintf("10Mb/s FDX");
+ linkspeed = ETHER_SPEED_10FDX;
+ }
+ else if (tempword & 0x00200000) { /* 10HD */
+ xprintf("10Mb/s HDX");
+ linkspeed = ETHER_SPEED_10HDX;
+ }
+ xprintf("\n");
+ }
+ else {
+ /* no link partner negotiation */
+ /* disable link for 1.3 seconds to break any existing connections */
+
+ /* xprintf("Disabling link, setting to 10mb half duplex\n"); */
+ dc21143_set_speed(sc, ETHER_SPEED_10HDX);
+ cfe_sleep(CFE_HZ/8);
+
+ tempword = READCSR(sc, R_CSR_SIASTATUS);
+
+ if ((tempword & 0x02) == 0) {
+ /* 100 mb signal present set to 100mb */
+ xprintf("No link partner... setting to 100mb/s HDX\n");
+ linkspeed = ETHER_SPEED_100HDX;
+ }
+ else if ((tempword & 0x04) == 0) {
+ /* 10 mb signal present */
+ xprintf("No link partner... setting to 10mb/s HDX\n");
+ linkspeed = ETHER_SPEED_10HDX;
+ }
+ else {
+ /* couldn't determine line speed, so set to 10mbs */
+ xprintf("Unknown; defaulting to 10Mb/s HDX\n");
+ linkspeed = ETHER_SPEED_10HDX;
+ }
+ }
+
+ dc21143_set_speed(sc, linkspeed);
+}
+
+static void
+dc21143_set_loopback(tulip_softc *sc, int mode)
+{
+ uint32_t v;
+
+ WRITECSR(sc, R_CSR_SIAMODE0, 0);
+ if (mode == ETHER_LOOPBACK_EXT) {
+ /* deal with CSRs 13-15 */
+ }
+ cfe_sleep(CFE_HZ/10); /* check this */
+
+ /* Update the SIA registers */
+ v = READCSR(sc, R_CSR_SIAMODE0);
+ WRITECSR(sc, R_CSR_SIAMODE0, v &~ 0xFFFF);
+ v = READCSR(sc, R_CSR_SIAMODE1);
+ WRITECSR(sc, R_CSR_SIAMODE1, v &~ 0xFFFF);
+ v = READCSR(sc, R_CSR_SIAMODE2);
+ WRITECSR(sc, R_CSR_SIAMODE2, v | 0xC000); /* WC of HCKR, RMP */
+ WRITECSR(sc, R_CSR_SIAMODE2, (v &~ 0xFFFF) | M_CSR15_GP_AUIBNC);
+
+ WRITECSR(sc, R_CSR_SIAMODE0, M_CSR13_CONN_NOT_RESET);
+}
+
+static void
+dc21143_hwinit(tulip_softc *sc)
+{
+ uint32_t v;
+ uint32_t csr6word, csr14word;
+
+ /* CSR0 - bus mode */
+ WRITECSR(sc, R_CSR_SIAMODE2, M_CSR15_CONFIG_GEPS_LEDS);
+#if TULIP_TUNE
+ v = V_CSR0_SKIPLEN(0) |
+ V_CSR0_CACHEALIGN(K_CSR0_ALIGN32) |
+ M_CSR0_READMULTENAB | M_CSR0_READLINEENAB |
+ M_CSR0_WRITEINVALENAB |
+ V_CSR0_BURSTLEN(K_CSR0_BURST32);
+#else
+ v = V_CSR0_SKIPLEN(0) |
+ V_CSR0_CACHEALIGN(K_CSR0_ALIGN128) |
+ V_CSR0_BURSTLEN(K_CSR0_BURST32);
+#endif
+#ifdef __MIPSEB
+ v |= M_CSR0_BIGENDIAN; /* big-endian data serialization */
+#endif
+ WRITECSR(sc, R_CSR_BUSMODE, v);
+
+ /* CSR6 - operation mode */
+ v = M_CSR6_PORTSEL |
+#if TULIP_TUNE
+ V_CSR6_THRESHCONTROL(K_CSR6_TXTHRES_128_72) |
+#else
+ M_CSR6_STOREFWD |
+#endif
+ M_CSR6_MBO |
+ M_CSR6_PCSFUNC |
+ M_CSR6_SCRAMMODE;
+ WRITECSR(sc, R_CSR_OPMODE, v);
+
+ /* About to muck the SIA, reset it.(?) */
+ /* WRITECSR(sc, R_CSR_SIASTATUS, 1); */
+
+ /* Must shut off all transmit/receive in order to attempt to
+ achieve Full Duplex */
+ csr6word = READCSR(sc, R_CSR_OPMODE);
+ WRITECSR(sc, R_CSR_OPMODE, csr6word &~ (M_CSR6_TXSTART | M_CSR6_RXSTART));
+ csr6word = READCSR(sc, R_CSR_OPMODE);
+
+ WRITECSR(sc, R_CSR_RXRING, PCIADDRX(sc, PHYSADDR(sc, sc->rxdscr_start)));
+ WRITECSR(sc, R_CSR_TXRING, PCIADDRX(sc, PHYSADDR(sc, sc->txdscr_start)));
+
+ if (sc->linkspeed == ETHER_SPEED_AUTO) {
+ dc21143_autonegotiate(sc);
+ }
+ else {
+ /* disable autonegotiate so we can set full duplex to on */
+ WRITECSR(sc, R_CSR_SIAMODE0, 0);
+ csr14word = READCSR(sc, R_CSR_SIAMODE1);
+ csr14word &=~ M_CSR14_AUTONEGOTIATE;
+ WRITECSR(sc, R_CSR_SIAMODE1, csr14word);
+ WRITECSR(sc, R_CSR_SIAMODE0, M_CSR13_CONN_NOT_RESET);
+
+ dc21143_set_speed(sc, sc->linkspeed);
+ }
+}
+
+
+static void
+dc21140_set_speed(tulip_softc *sc, int speed, int autoneg)
+{
+ uint16_t control;
+ uint16_t pcr;
+ uint32_t opmode = 0;
+
+ pcr = mii_read_register(sc, 0x17);
+ pcr |= (0x400|0x100|0x40|0x20);
+ mii_write_register(sc, 0x17, pcr);
+
+ control = mii_read_register(sc, MII_BMCR);
+
+ if (!autoneg) {
+ control &=~ (BMCR_ANENABLE | BMCR_RESTARTAN);
+ mii_write_register(sc, MII_BMCR, control);
+ control &=~ (BMCR_SPEED0 | BMCR_SPEED1 | BMCR_DUPLEX);
+ }
+
+ switch (speed) {
+ case ETHER_SPEED_10HDX:
+ default:
+ opmode = M_CSR6_SPEED_10_MII;
+ break;
+ case ETHER_SPEED_10FDX:
+ control |= BMCR_DUPLEX;
+ opmode = M_CSR6_SPEED_10_MII | M_CSR6_FULLDUPLEX;
+ break;
+ case ETHER_SPEED_100HDX:
+ control |= BMCR_SPEED100;
+ opmode = M_CSR6_SPEED_100_MII;
+ break;
+ case ETHER_SPEED_100FDX:
+ control |= BMCR_SPEED100 | BMCR_DUPLEX ;
+ opmode = M_CSR6_SPEED_100_MII | M_CSR6_FULLDUPLEX;
+ break;
+ }
+
+ if (!autoneg)
+ mii_write_register(sc, MII_BMCR, control);
+
+ opmode |= M_CSR6_MBO;
+#if TULIP_TUNE
+ opmode |= V_CSR6_THRESHCONTROL(K_CSR6_TXTHRES_128_72);
+#else
+ opmode |= M_CSR6_STOREFWD;
+#endif
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+#if 0
+ xprintf("setspeed PHY\n"); mii_dump(sc);
+#endif
+}
+
+static void
+dc21140_autonegotiate(tulip_softc *sc)
+{
+ uint16_t control, status, cap;
+ unsigned int timeout;
+ int linkspeed;
+ int autoneg;
+
+ linkspeed = ETHER_SPEED_UNKNOWN;
+
+ /* Read twice to clear latching bits */
+ status = mii_read_register(sc, MII_BMSR);
+ status = mii_read_register(sc, MII_BMSR);
+#if 0
+ xprintf("query PHY\n"); mii_dump(sc);
+#endif
+
+ if ((status & (BMSR_AUTONEG | BMSR_LINKSTAT)) ==
+ (BMSR_AUTONEG | BMSR_LINKSTAT))
+ control = mii_read_register(sc, MII_BMCR);
+ else {
+ /* reset the PHY */
+ mii_write_register(sc, MII_BMCR, BMCR_RESET);
+ timeout = 3000;
+ for (;;) {
+ control = mii_read_register(sc, MII_BMCR);
+ if ((control && BMCR_RESET) == 0) break;
+ cfe_sleep(CFE_HZ/2);
+ timeout -= 500;
+ if (timeout <= 0) break;
+ }
+ if ((control & BMCR_RESET) != 0) {
+ xprintf("DC21140: PHY reset failed\n");
+ return;
+ }
+
+ status = mii_read_register(sc, MII_BMSR);
+ cap = ((status >> 6) & (ANAR_TXFD | ANAR_TXHD | ANAR_10FD | ANAR_10HD))
+ | PSB_802_3;
+ mii_write_register(sc, MII_ANAR, cap);
+ control |= (BMCR_ANENABLE | BMCR_RESTARTAN);
+ mii_write_register(sc, MII_BMCR, control);
+
+ timeout = 3000;
+ for (;;) {
+ status = mii_read_register(sc, MII_BMSR);
+ if ((status & BMSR_ANCOMPLETE) != 0) break;
+ cfe_sleep(CFE_HZ/2);
+ timeout -= 500;
+ if (timeout <= 0) break;
+ }
+#if 0
+ xprintf("done PHY\n"); mii_dump(sc);
+#endif
+ }
+
+ if ((status & BMSR_ANCOMPLETE) != 0) {
+ /* A link partner was negogiated... */
+
+ uint16_t remote = mii_read_register(sc, MII_ANLPAR);
+
+ autoneg = 1;
+ xprintf("DC21140: Negotiated ");
+ if ((remote & ANLPAR_TXFD) != 0) {
+ xprintf("100Mb/s FDX");
+ linkspeed = ETHER_SPEED_100FDX;
+ }
+ else if ((remote & ANLPAR_TXHD) != 0) {
+ xprintf("100Mb/s HDX");
+ linkspeed = ETHER_SPEED_100HDX;
+ }
+ else if ((remote & ANLPAR_10FD) != 0) {
+ xprintf("10Mb/s FDX");
+ linkspeed = ETHER_SPEED_10FDX;
+ }
+ else if ((remote & ANLPAR_10HD) != 0) {
+ xprintf("10Mb/s HDX");
+ linkspeed = ETHER_SPEED_10HDX;
+ }
+ xprintf("\n");
+ }
+ else {
+ /* no link partner negotiation */
+
+ autoneg = 0;
+ xprintf("DC21140: MII negotiation failed, assuming 10BT\n");
+ control &=~ (BMCR_ANENABLE | BMCR_RESTARTAN);
+ mii_write_register(sc, MII_BMCR, control);
+ linkspeed = ETHER_SPEED_10HDX;
+ }
+
+ if ((status & BMSR_LINKSTAT) == 0)
+ mii_write_register(sc, MII_BMCR, control);
+ dc21140_set_speed(sc, linkspeed, autoneg);
+
+ status = mii_read_register(sc, MII_BMSR); /* clear latching bits */
+#if 0
+ xprintf("final PHY\n"); mii_dump(sc);
+#endif
+}
+
+static void
+dc21140_set_loopback(tulip_softc *sc, int mode)
+{
+ if (mode == ETHER_LOOPBACK_EXT)
+ xprintf("DC21140: external loopback mode NYI\n");
+}
+
+static void
+dc21140_hwinit(tulip_softc *sc)
+{
+ uint32_t v;
+ uint32_t csr6word;
+
+ /* The following assume GP port bits wired per the DEC reference design.
+ XXX Interpret the srom initialization strings instead */
+ WRITECSR(sc, R_CSR_GENPORT, M_CSR12_CONTROL | 0x1F);
+ WRITECSR(sc, R_CSR_GENPORT, 0); /* release PHY reset */
+
+ /* Select MII interface */
+ WRITECSR(sc, R_CSR_OPMODE, M_CSR6_PORTSEL);
+ RESET_ADAPTER(sc);
+
+ mii_probe(sc);
+
+ /* CSR0 - bus mode */
+#if TULIP_TUNE
+ v = V_CSR0_SKIPLEN(0) |
+ V_CSR0_CACHEALIGN(K_CSR0_ALIGN32) |
+ M_CSR0_READMULTENAB | M_CSR0_READLINEENAB |
+ M_CSR0_WRITEINVALENAB |
+ V_CSR0_BURSTLEN(K_CSR0_BURST32);
+#else
+ v = V_CSR0_SKIPLEN(0) |
+ V_CSR0_CACHEALIGN(K_CSR0_ALIGN128) |
+ V_CSR0_BURSTLEN(K_CSR0_BURST32);
+#endif
+#ifdef __MIPSEB
+ v |= M_CSR0_BIGENDIAN; /* big-endian data serialization */
+#endif
+ WRITECSR(sc, R_CSR_BUSMODE, v);
+
+ /* CSR6 - operation mode */
+ v = M_CSR6_PORTSEL |
+#if TULIP_TUNE
+ V_CSR6_THRESHCONTROL(K_CSR6_TXTHRES_128_72) |
+#else
+ M_CSR6_STOREFWD |
+#endif
+ M_CSR6_MBO;
+ WRITECSR(sc, R_CSR_OPMODE, v);
+
+ /* Must shut off all transmit/receive in order to attempt to
+ achieve Full Duplex */
+ csr6word = READCSR(sc, R_CSR_OPMODE);
+ WRITECSR(sc, R_CSR_OPMODE, csr6word &~ (M_CSR6_TXSTART | M_CSR6_RXSTART));
+ csr6word = READCSR(sc, R_CSR_OPMODE);
+
+ WRITECSR(sc, R_CSR_RXRING, PCIADDRX(sc, PHYSADDR(sc, sc->rxdscr_start)));
+ WRITECSR(sc, R_CSR_TXRING, PCIADDRX(sc, PHYSADDR(sc, sc->txdscr_start)));
+
+ if (sc->linkspeed == ETHER_SPEED_AUTO) {
+ dc21140_autonegotiate(sc);
+ }
+ else {
+ dc21140_set_speed(sc, sc->linkspeed, 0);
+ }
+}
+
+
+static void
+dc21041_set_loopback(tulip_softc *sc, int mode)
+{
+ uint32_t v;
+
+ WRITECSR(sc, R_CSR_SIAMODE0, 0);
+ if (mode == ETHER_LOOPBACK_EXT) {
+ /* deal with CSRs 13-15 */
+ }
+ cfe_sleep(CFE_HZ/10); /* check this */
+
+ /* Update the SIA registers */
+ v = READCSR(sc, R_CSR_SIAMODE0);
+ WRITECSR(sc, R_CSR_SIAMODE0, v &~ 0xFFFF);
+ WRITECSR(sc, R_CSR_SIAMODE1, 0x7A3F);
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x0008);
+
+ WRITECSR(sc, R_CSR_SIAMODE0, 0xEF01);
+}
+
+static void
+dc21041_hwinit(tulip_softc *sc)
+{
+ uint32_t v;
+ uint32_t opmode;
+
+ /* CSR0 - bus mode */
+ v = V_CSR0_SKIPLEN(0) |
+ V_CSR0_CACHEALIGN(K_CSR0_ALIGN128) |
+ V_CSR0_BURSTLEN(K_CSR0_BURST32);
+#ifdef __MIPSEB
+ v |= M_CSR0_BIGENDIAN; /* big-endian data serialization */
+#endif
+ WRITECSR(sc, R_CSR_BUSMODE, v);
+
+ /* set initial interrupt mask here? */
+
+ WRITECSR(sc, R_CSR_RXRING, PCIADDRX(sc, PHYSADDR(sc, sc->rxdscr_start)));
+ WRITECSR(sc, R_CSR_TXRING, PCIADDRX(sc, PHYSADDR(sc, sc->txdscr_start)));
+
+ WRITECSR(sc, R_CSR_SIAMODE0, 0);
+
+ /* For now, always force 10BT, HDX */
+ WRITECSR(sc, R_CSR_SIAMODE1, 0x7F3F);
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x0008);
+ opmode = M_CSR6_SPEED_10;
+
+ WRITECSR(sc, R_CSR_SIAMODE0, 0xEF01);
+ cfe_sleep(CFE_HZ/10);
+
+ opmode |= V_CSR6_THRESHCONTROL(K_CSR6_TXTHRES_128_72);
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+}
+
+
+static void
+tulip_hwinit(tulip_softc *sc)
+{
+ if (sc->state == eth_state_uninit) {
+ RESET_ADAPTER(sc);
+ sc->state = eth_state_off;
+ sc->bus_errors = 0;
+
+ switch (sc->device) {
+ case K_PCI_ID_DC21041:
+ dc21041_hwinit(sc);
+ break;
+ case K_PCI_ID_DC21140:
+ dc21140_hwinit(sc);
+ break;
+ case K_PCI_ID_DC21143:
+ dc21143_hwinit(sc);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+
+static void
+tulip_isr(tulip_softc *sc)
+{
+ uint32_t status;
+ uint32_t csr5;
+
+ for (;;) {
+
+ /* Read the interrupt status. */
+ csr5 = READCSR(sc, R_CSR_STATUS);
+// status &= sc->intmask; /* keep only the bits we like. */
+ status = csr5 & (
+ M_CSR5_RXINT | M_CSR5_RXBUFUNAVAIL |
+ M_CSR5_TXINT | M_CSR5_TXUNDERFLOW |
+ M_CSR5_FATALBUSERROR);
+
+ /* if there are no more interrupts, leave now. */
+ if (status == 0) break;
+
+ /* Clear the pending interrupt. */
+ WRITECSR(sc, R_CSR_STATUS, status);
+
+ /* Now, test each unmasked bit in the interrupt register and
+ handle each interrupt type appropriately. */
+
+ if (status & M_CSR5_FATALBUSERROR) {
+ xprintf("DC21143: bus error %02x\n", G_CSR5_ERRORBITS(csr5));
+ dumpstat(sc);
+ sc->bus_errors++;
+ if (sc->bus_errors >= 2) {
+ dumpcsrs(sc);
+ RESET_ADAPTER(sc);
+ sc->state = eth_state_off;
+ sc->bus_errors = 0;
+ }
+ }
+
+ if (status & M_CSR5_RXINT) {
+ tulip_procrxring(sc);
+ }
+
+ if (status & M_CSR5_TXINT) {
+ tulip_proctxring(sc);
+ }
+
+ if (status & (M_CSR5_TXUNDERFLOW | M_CSR5_RXBUFUNAVAIL)) {
+ if (status & M_CSR5_TXUNDERFLOW) {
+ xprintf("DC21143: tx underrun, %08x\n", csr5);
+ /* Try to restart */
+ WRITECSR(sc, R_CSR_TXPOLL, 1);
+ }
+ if (status & M_CSR5_RXBUFUNAVAIL) {
+ /* Try to restart */
+ WRITECSR(sc, R_CSR_RXPOLL, 1);
+ }
+ }
+ }
+}
+
+
+static void
+tulip_start(tulip_softc *sc)
+{
+ uint32_t opmode;
+ int idx;
+ tulip_cam *cam;
+ eth_pkt_t *pkt;
+
+ tulip_hwinit(sc);
+
+ WRITECSR(sc, R_CSR_RXRING, PCIADDRX(sc, PHYSADDR(sc, sc->rxdscr_start)));
+ WRITECSR(sc, R_CSR_TXRING, PCIADDRX(sc, PHYSADDR(sc, sc->txdscr_start)));
+
+ opmode = READCSR(sc, R_CSR_OPMODE);
+ opmode &=~ M_CSR6_OPMODE; /* no loopback */
+ opmode |= (M_CSR6_TXSTART | M_CSR6_RXSTART);
+
+ sc->intmask = 0;
+ WRITECSR(sc, R_CSR_INTMASK, 0); /* no interrupts */
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+
+ pkt = eth_alloc_pkt(sc);
+ if (pkt) {
+ pkt->length = CAM_SETUP_BUFFER_SIZE;
+ cam = (tulip_cam *) pkt->buffer;
+
+#ifdef __MIPSEB
+ cam->p.physical[0][0] = (((uint32_t) sc->hwaddr[0] << 8) |
+ (uint32_t) sc->hwaddr[1]) << 16;
+ cam->p.physical[0][1] = (((uint32_t) sc->hwaddr[2] << 8) |
+ (uint32_t) sc->hwaddr[3]) << 16;
+ cam->p.physical[0][2] = (((uint32_t) sc->hwaddr[4] << 8) |
+ (uint32_t) sc->hwaddr[5]) << 16;
+ for (idx = 1; idx < CAM_PERFECT_ENTRIES; idx++) {
+ cam->p.physical[idx][0] = 0xFFFF0000;
+ cam->p.physical[idx][1] = 0xFFFF0000;
+ cam->p.physical[idx][2] = 0xFFFF0000;
+ }
+#else
+ cam->p.physical[0][0] = ((uint32_t) sc->hwaddr[0]) |
+ (((uint32_t) sc->hwaddr[1]) << 8);
+ cam->p.physical[0][1] = ((uint32_t) sc->hwaddr[2]) |
+ (((uint32_t) sc->hwaddr[3]) << 8);
+ cam->p.physical[0][2] = ((uint32_t) sc->hwaddr[4]) |
+ (((uint32_t) sc->hwaddr[5]) << 8);
+ for (idx = 1; idx < CAM_PERFECT_ENTRIES; idx++) {
+ cam->p.physical[idx][0] = 0x0000FFFF;
+ cam->p.physical[idx][1] = 0x0000FFFF;
+ cam->p.physical[idx][2] = 0x0000FFFF;
+ }
+#endif
+
+ pkt->flags |= ETH_TX_SETUP;
+ if (tulip_transmit(sc, pkt) != 0) {
+ xprintf("DC21143: failed setup\n");
+ dumpstat(sc);
+ eth_free_pkt(sc, pkt);
+ return;
+ }
+ sc->state = eth_state_setup;
+ }
+}
+
+static void
+tulip_stop(tulip_softc *sc)
+{
+ uint32_t opmode;
+ uint32_t status;
+ int count;
+
+ WRITECSR(sc, R_CSR_INTMASK, 0);
+ sc->intmask = 0;
+
+ opmode = READCSR(sc, R_CSR_OPMODE);
+ opmode &=~ (M_CSR6_TXSTART | M_CSR6_RXSTART);
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+
+ /* wait for any DMA activity to terminate */
+ for (count = 0; count <= 130; count++) {
+ status = READCSR(sc, R_CSR_STATUS);
+ if ((status & (M_CSR5_RXPROCSTATE | M_CSR5_TXPROCSTATE)) == 0)
+ break;
+ cfe_sleep(CFE_HZ/10);
+ }
+ if (count > 130) {
+ xprintf("DC21143: idle state not achieved\n");
+ dumpstat(sc);
+ }
+}
+
+
+static void
+tulip_start_loopback(tulip_softc *sc, int mode)
+{
+ uint32_t opmode;
+
+ opmode = READCSR(sc, R_CSR_OPMODE);
+
+ switch (sc->device) {
+ case K_PCI_ID_DC21041:
+ dc21041_set_loopback(sc, mode);
+ break;
+ case K_PCI_ID_DC21140:
+ dc21140_set_loopback(sc, mode);
+ break;
+ case K_PCI_ID_DC21143:
+ dc21143_set_loopback(sc, mode);
+ break;
+ default:
+ break;
+ }
+ cfe_sleep(CFE_HZ/10);
+
+ WRITECSR(sc, R_CSR_RXRING, PCIADDRX(sc, PHYSADDR(sc, sc->rxdscr_start)));
+ WRITECSR(sc, R_CSR_TXRING, PCIADDRX(sc, PHYSADDR(sc, sc->txdscr_start)));
+
+ sc->intmask = 0; /* no interrupts */
+ WRITECSR(sc, R_CSR_INTMASK, 0);
+
+ opmode &=~ (M_CSR6_OPMODE | M_CSR6_FULLDUPLEX);
+ opmode |= M_CSR6_PORTSEL;
+ if (mode == ETHER_LOOPBACK_EXT)
+ opmode |= M_CSR6_EXTLOOPBACK;
+ else
+ opmode |= M_CSR6_INTLOOPBACK;
+ opmode |= M_CSR6_TXSTART | M_CSR6_RXSTART;
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+}
+
+
+/* *********************************************************************
+ * ETH_PARSE_XDIGIT(c)
+ *
+ * Parse a hex digit, returning its value
+ *
+ * Input parameters:
+ * c - character
+ *
+ * Return value:
+ * hex value, or -1 if invalid
+ ********************************************************************* */
+static int
+eth_parse_xdigit(char c)
+{
+ int digit;
+
+ if ((c >= '0') && (c <= '9')) digit = c - '0';
+ else if ((c >= 'a') && (c <= 'f')) digit = c - 'a' + 10;
+ else if ((c >= 'A') && (c <= 'F')) digit = c - 'A' + 10;
+ else digit = -1;
+
+ return digit;
+}
+
+/* *********************************************************************
+ * ETH_PARSE_HWADDR(str,hwaddr)
+ *
+ * Convert a string in the form xx:xx:xx:xx:xx:xx into a 6-byte
+ * Ethernet address.
+ *
+ * Input parameters:
+ * str - string
+ * hwaddr - pointer to hardware address
+ *
+ * Return value:
+ * 0 if ok, else -1
+ ********************************************************************* */
+static int
+eth_parse_hwaddr(char *str, uint8_t *hwaddr)
+{
+ int digit1, digit2;
+ int idx = ENET_ADDR_LEN;
+
+ while (*str && (idx > 0)) {
+ digit1 = eth_parse_xdigit(*str);
+ if (digit1 < 0) return -1;
+ str++;
+ if (!*str) return -1;
+
+ if ((*str == ':') || (*str == '-')) {
+ digit2 = digit1;
+ digit1 = 0;
+ }
+ else {
+ digit2 = eth_parse_xdigit(*str);
+ if (digit2 < 0) return -1;
+ str++;
+ }
+
+ *hwaddr++ = (digit1 << 4) | digit2;
+ idx--;
+
+ if ((*str == ':') || (*str == '-'))
+ str++;
+ }
+ return 0;
+}
+
+/* *********************************************************************
+ * ETH_INCR_HWADDR(hwaddr,incr)
+ *
+ * Increment a 6-byte Ethernet hardware address, with carries
+ *
+ * Input parameters:
+ * hwaddr - pointer to hardware address
+ * incr - desired increment
+ *
+ * Return value:
+ * none
+ ********************************************************************* */
+static void
+eth_incr_hwaddr(uint8_t *hwaddr, unsigned incr)
+{
+ int idx;
+ int carry;
+
+ idx = 5;
+ carry = incr;
+ while (idx >= 0 && carry != 0) {
+ unsigned sum = hwaddr[idx] + carry;
+
+ hwaddr[idx] = sum & 0xff;
+ carry = sum >> 8;
+ idx--;
+ }
+}
+
+
+/* *********************************************************************
+ * Declarations for CFE Device Driver Interface routines
+ ********************************************************************* */
+
+static int tulip_ether_open(cfe_devctx_t *ctx);
+static int tulip_ether_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int tulip_ether_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int tulip_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int tulip_ether_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int tulip_ether_close(cfe_devctx_t *ctx);
+
+/* *********************************************************************
+ * CFE Device Driver dispatch structure
+ ********************************************************************* */
+
+const static cfe_devdisp_t tulip_ether_dispatch = {
+ tulip_ether_open,
+ tulip_ether_read,
+ tulip_ether_inpstat,
+ tulip_ether_write,
+ tulip_ether_ioctl,
+ tulip_ether_close,
+ NULL,
+ NULL
+};
+
+/* *********************************************************************
+ * CFE Device Driver descriptor
+ ********************************************************************* */
+
+const cfe_driver_t dc21143drv = {
+ "DC2114x Ethernet",
+ "eth",
+ CFE_DEV_NETWORK,
+ &tulip_ether_dispatch,
+ tulip_ether_probe
+};
+
+
+static int
+tulip_ether_attach(cfe_driver_t *drv,
+ pcitag_t tag, int index, uint8_t hwaddr[], int host)
+{
+ tulip_softc *softc;
+ uint32_t device;
+ uint32_t class;
+ uint32_t reg;
+ phys_addr_t pa;
+ char descr[100];
+ uint8_t romaddr[ENET_ADDR_LEN];
+#if 0 /* temporary */
+ int i;
+ uint8_t srom[SROM_SIZE];
+#endif
+
+ device = pci_conf_read(tag, R_CFG_CFID);
+
+ class = pci_conf_read(tag, R_CFG_CFRV);
+
+ reg = pci_conf_read(tag, R_CFG_CPMS);
+
+ reg = pci_conf_read(tag, R_CFG_CFDD);
+ pci_conf_write(tag, R_CFG_CFDD, 0);
+ reg = pci_conf_read(tag, R_CFG_CFDD);
+
+#if 1
+ /* Use memory space for the CSRs */
+ pci_map_mem(tag, R_CFG_CBMA, PCI_MATCH_BITS, &pa);
+#else
+ /* Use i/o space for the CSRs */
+ pci_map_io(tag, R_CFG_CBIO, PCI_MATCH_BITS, &pa);
+#endif
+
+ softc = (tulip_softc *) KMALLOC(sizeof(tulip_softc), 0);
+ if (softc == NULL) {
+ xprintf("DC2114x: No memory to complete probe\n");
+ return 0;
+ }
+
+ memset(softc, 0, sizeof(*softc));
+
+ softc->membase = (uint32_t)pa;
+
+ /* If we are in Host mode, we can receive interrupts. Otherwise,
+ we can see the CSRs but our CPU will not get interrupts. */
+ if (host)
+ softc->irq = pci_conf_read(tag, R_CFG_CFIT) & 0xFF;
+ else
+ softc->irq = 0xFF;
+
+ softc->tag = tag;
+ softc->device = PCI_PRODUCT(device);
+ softc->revision = PCI_REVISION(class);
+#if 1
+ softc->linkspeed = ETHER_SPEED_AUTO; /* select autonegotiation */
+#else
+ softc->linkspeed = ETHER_SPEED_100HDX; /* 100 Mbps, full duplex */
+#endif
+ memcpy(softc->hwaddr, hwaddr, ENET_ADDR_LEN);
+
+ tulip_init(softc);
+
+ /* Prefer address in srom */
+ if (srom_read_addr(softc, romaddr) == 0)
+ memcpy(softc->hwaddr, romaddr, ENET_ADDR_LEN);
+
+ softc->state = eth_state_uninit;
+
+ xsprintf(descr, "%s at 0x%X (%02x-%02x-%02x-%02x-%02x-%02x)",
+ drv->drv_description, softc->membase,
+ softc->hwaddr[0], softc->hwaddr[1], softc->hwaddr[2],
+ softc->hwaddr[3], softc->hwaddr[4], softc->hwaddr[5]);
+ cfe_attach(drv, softc, NULL, descr);
+ return 1;
+}
+
+
+/* *********************************************************************
+ * TULIP_ETHER_PROBE(drv,probe_a,probe_b,probe_ptr)
+ *
+ * Probe and install drivers for all DC2114x Ethernet controllers.
+ * For each, creates a context structure and attaches to the
+ * specified MAC devices.
+ *
+ * Input parameters:
+ * drv - driver descriptor
+ * probe_a - not used
+ * probe_b - not used
+ * probe_ptr - string pointer to hardware address for the first
+ * MAC, in the form xx:xx:xx:xx:xx:xx
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void
+tulip_ether_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ int index;
+ int n;
+ uint8_t hwaddr[ENET_ADDR_LEN];
+
+ if (probe_ptr)
+ eth_parse_hwaddr((char *) probe_ptr, hwaddr);
+ else {
+ /* use default address 40-00-00-10-11-11 */
+ hwaddr[0] = 0x40; hwaddr[1] = 0x00;
+ hwaddr[2] = 0x00; hwaddr[3] = 0x10;
+ hwaddr[4] = 0x11; hwaddr[5] = 0x11;
+ }
+
+ n = 0;
+ index = 0;
+ for (;;) {
+ pcitag_t tag;
+ pcireg_t device;
+
+ if (pci_find_class(PCI_CLASS_NETWORK, index, &tag) != 0)
+ break;
+
+ index++;
+
+ device = pci_conf_read(tag, R_CFG_CFID);
+ if (PCI_VENDOR(device) != K_PCI_VENDOR_DEC)
+ continue;
+ switch (PCI_PRODUCT(device)) {
+ case K_PCI_ID_DC21041:
+ break;
+ case K_PCI_ID_DC21140:
+ break;
+ case K_PCI_ID_DC21143:
+ break;
+ default:
+ continue;
+ }
+
+ tulip_ether_attach(drv, tag, index, hwaddr, 1);
+
+ n++;
+ eth_incr_hwaddr(hwaddr, 1);
+ }
+}
+
+
+/* The functions below are called via the dispatch vector for the 2114x. */
+
+/* *********************************************************************
+ * TULIP_ETHER_OPEN(ctx)
+ *
+ * Open the Ethernet device. The MAC is reset, initialized, and
+ * prepared to receive and send packets.
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+tulip_ether_open(cfe_devctx_t *ctx)
+{
+ tulip_softc *softc = ctx->dev_softc;
+
+ if (softc->state == eth_state_on)
+ tulip_stop(softc);
+
+ tulip_start(softc);
+ softc->state = eth_state_on;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * TULIP_ETHER_READ(ctx,buffer)
+ *
+ * Read a packet from the Ethernet device. If no packets are
+ * available, the read will succeed but return 0 bytes.
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ * buffer - pointer to buffer descriptor.
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+tulip_ether_read(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ tulip_softc *softc = ctx->dev_softc;
+ eth_pkt_t *pkt;
+ int blen;
+
+ if (softc->state != eth_state_on) return -1;
+
+ tulip_isr(softc);
+
+ pkt = (eth_pkt_t *) q_deqnext(&(softc->rxqueue));
+
+ if (pkt == NULL) {
+ buffer->buf_retlen = 0;
+ return 0;
+ }
+
+ blen = buffer->buf_length;
+ if (blen > pkt->length) blen = pkt->length;
+
+ memcpy(buffer->buf_ptr, pkt->buffer, blen);
+ buffer->buf_retlen = blen;
+
+ eth_free_pkt(softc,pkt);
+ tulip_fillrxring(softc);
+ tulip_isr(softc);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * TULIP_ETHER_INPSTAT(ctx,inpstat)
+ *
+ * Check for received packets on the Ethernet device
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ * inpstat - pointer to input status structure
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+tulip_ether_inpstat(cfe_devctx_t *ctx, iocb_inpstat_t *inpstat)
+{
+ tulip_softc *softc = ctx->dev_softc;
+
+ if (softc->state != eth_state_on) return -1;
+
+ tulip_isr(softc);
+
+ inpstat->inp_status = (q_isempty(&(softc->rxqueue))) ? 0 : 1;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * TULIP_ETHER_WRITE(ctx,buffer)
+ *
+ * Write a packet to the Ethernet device.
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ * buffer - pointer to buffer descriptor.
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+tulip_ether_write(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ tulip_softc *softc = ctx->dev_softc;
+ eth_pkt_t *pkt;
+ int blen;
+
+ if (softc->state != eth_state_on) return -1;
+
+ pkt = eth_alloc_pkt(softc);
+ if (!pkt) return -1;
+
+ blen = buffer->buf_length;
+ if (blen > pkt->length) blen = pkt->length;
+
+ memcpy(pkt->buffer, buffer->buf_ptr, blen);
+ pkt->length = blen;
+
+ tulip_isr(softc);
+
+ if (tulip_transmit(softc, pkt) != 0) {
+ eth_free_pkt(softc,pkt);
+ return -1;
+ }
+
+ tulip_isr(softc);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * TULIP_ETHER_IOCTL(ctx,buffer)
+ *
+ * Do device-specific I/O control operations for the device
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ * buffer - pointer to buffer descriptor.
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+tulip_ether_ioctl(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ tulip_softc *softc = ctx->dev_softc;
+ int mode;
+
+ switch ((int)buffer->buf_ioctlcmd) {
+ case IOCTL_ETHER_GETHWADDR:
+ memcpy(buffer->buf_ptr, softc->hwaddr, sizeof(softc->hwaddr));
+ return 0;
+
+ case IOCTL_ETHER_SETHWADDR:
+ return -1; /* need to do this carefully */
+
+ /* XXX IOCTLs to set speed, etc.? */
+
+ case IOCTL_ETHER_GETLOOPBACK:
+ *((int *) buffer) = 0; /* XXX place holder */
+ return 0;
+
+ case IOCTL_ETHER_SETLOOPBACK:
+ tulip_stop(softc);
+ tulip_resetrings(softc);
+ mode = *((int *) buffer->buf_ptr);
+ if (mode == ETHER_LOOPBACK_INT || mode == ETHER_LOOPBACK_EXT) {
+ tulip_start_loopback(softc, mode);
+ }
+ else if (mode == ETHER_LOOPBACK_OFF) {
+ tulip_start(softc);
+ }
+ softc->state = eth_state_on;
+ return 0;
+
+ default:
+ return -1;
+ }
+}
+
+/* *********************************************************************
+ * TULIP_ETHER_CLOSE(ctx)
+ *
+ * Close the Ethernet device.
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+tulip_ether_close(cfe_devctx_t *ctx)
+{
+ tulip_softc *softc = ctx->dev_softc;
+
+ tulip_stop(softc);
+ softc->state = eth_state_off;
+
+ /* resynchronize descriptor rings */
+ tulip_resetrings(softc);
+
+ return 0;
+}
diff --git a/cfe/cfe/dev/dev_dp83815.c b/cfe/cfe/dev/dev_dp83815.c
new file mode 100644
index 0000000..b9fb644
--- /dev/null
+++ b/cfe/cfe/dev/dev_dp83815.c
@@ -0,0 +1,2290 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * NS DP83815 Ethernet Driver File: dev_dp83815.c
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "sbmips.h"
+
+#ifndef _SB_MAKE64
+#define _SB_MAKE64(x) ((uint64_t)(x))
+#endif
+#ifndef _SB_MAKEMASK1
+#define _SB_MAKEMASK1(n) (_SB_MAKE64(1) << _SB_MAKE64(n))
+#endif
+
+#include "lib_types.h"
+#include "lib_hssubr.h"
+#include "lib_malloc.h"
+#include "lib_string.h"
+#define blockcopy memcpy
+#include "lib_printf.h"
+#include "lib_queue.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+#include "cfe_timer.h"
+#include "cfe_error.h"
+#include "cfe_irq.h"
+
+#include "pcivar.h"
+#include "pcireg.h"
+
+#include "dp83815.h"
+#include "mii.h"
+
+/* This is a driver for the National Semiconductor DP83815 (MacPhyter)
+ 10/100 MAC with integrated PHY.
+
+ The current version has been developed for the Netgear FA311 and
+ FA312 NICs. These include an EEPROM with automatically loaded
+ setup information that includes station address filtering.
+ Operation without such an EEPROM has not been tested.
+
+ This SB1250 version takes advantage of DMA coherence and uses
+ "preserve bit lanes" addresses for all accesses that cross the
+ ZBbus-PCI bridge. */
+
+#ifndef MACPHYTER_DEBUG
+#define MACPHYTER_DEBUG 0
+#endif
+#ifndef MACPHYTER_TEST
+#define MACPHYTER_TEST 0
+#endif
+
+/* Set IPOLL to drive processing through the pseudo-interrupt
+ dispatcher. Set XPOLL to drive processing by an external polling
+ agent. Setting both is ok. */
+
+#ifndef IPOLL
+#define IPOLL 0
+#endif
+#ifndef XPOLL
+#define XPOLL 1
+#endif
+
+#define ENET_ADDR_LEN 6 /* size of an ethernet address */
+#define MIN_ETHER_PACK 64 /* min size of a packet */
+#define MAX_ETHER_PACK 1518 /* max size of a packet */
+#define CRC_SIZE 4 /* size of CRC field */
+
+/* Packet buffers. For the DP83815, an rx packet must be aligned to a
+ 32-bit word boundary, and we would like it aligned to a cache line
+ boundary for performance. Also, the buffers "should" be allocated
+ in 32 byte multiples (5.3.2). */
+
+#define ETH_PKTBUF_LEN (((MAX_ETHER_PACK+31)/32)*32)
+
+#if __long64
+typedef struct eth_pkt_s {
+ queue_t next; /* 16 */
+ uint8_t *buffer; /* 8 */
+ uint32_t flags; /* 4 */
+ int32_t length; /* 4 */
+ uint8_t data[ETH_PKTBUF_LEN];
+} eth_pkt_t;
+#else
+typedef struct eth_pkt_s {
+ queue_t next; /* 8 */
+ uint8_t *buffer; /* 4 */
+ uint32_t flags; /* 4 */
+ int32_t length; /* 4 */
+ uint32_t unused[3]; /* 12 */
+ uint8_t data[ETH_PKTBUF_LEN];
+} eth_pkt_t;
+#endif
+
+#define CACHE_ALIGN 32
+#define ETH_PKTBUF_LINES ((sizeof(eth_pkt_t) + (CACHE_ALIGN-1))/CACHE_ALIGN)
+#define ETH_PKTBUF_SIZE (ETH_PKTBUF_LINES*CACHE_ALIGN)
+#define ETH_PKTBUF_OFFSET (offsetof(eth_pkt_t, data))
+
+#define ETH_PKT_BASE(data) ((eth_pkt_t *)((data) - ETH_PKTBUF_OFFSET))
+
+/* packet flags */
+#define ETH_TX_SETUP 1 /* assumes Perfect Filtering format */
+
+static void
+show_packet(char c, eth_pkt_t *pkt)
+{
+ int i;
+ int n = (pkt->length < 32 ? pkt->length : 32);
+
+ xprintf("%c[%4d]:", c, pkt->length);
+ for (i = 0; i < n; i++) {
+ if (i % 4 == 0)
+ xprintf(" ");
+ xprintf("%02x", pkt->buffer[i]);
+ }
+ xprintf("\n");
+}
+
+
+/* Descriptor structures. NOTE: To avoid having descriptors straddle
+ cache lines, we append a pad word, ignored by DMA, to each. */
+
+typedef struct rx_dscr {
+ pci_addr_t rxd_link;
+ uint32_t rxd_cmdsts;
+ pci_addr_t rxd_bufptr;
+ uint32_t rxd_pad;
+} rx_dscr;
+
+typedef struct tx_dscr {
+ pci_addr_t txd_link;
+ uint32_t txd_cmdsts;
+ pci_addr_t txd_bufptr;
+ uint32_t txd_pad;
+} tx_dscr;
+
+
+/* Driver data structures */
+
+typedef enum {
+ eth_state_uninit,
+ eth_state_off,
+ eth_state_on,
+ eth_state_broken
+} eth_state_t;
+
+#define ETH_PKTPOOL_SIZE 32
+
+typedef struct dp83815_softc {
+ uint32_t membase;
+ uint8_t irq; /* interrupt mapping (used if IPOLL) */
+ pcitag_t tag; /* tag for configuration registers */
+
+ uint8_t hwaddr[ENET_ADDR_LEN];
+ uint16_t device; /* chip device code */
+ uint8_t revision; /* chip revision and step */
+
+ eth_state_t state; /* current state */
+ uint32_t intmask; /* interrupt mask */
+
+ /* These fields are set before calling dp83815_hwinit */
+ int linkspeed; /* encodings from cfe_ioctl */
+ int loopback;
+
+ /* Packet free list */
+ queue_t freelist;
+ uint8_t *pktpool;
+ queue_t rxqueue;
+
+ /* The descriptor tables */
+ uint8_t *rxdscrmem; /* receive descriptors */
+ uint8_t *txdscrmem; /* transmit descriptors */
+
+ /* These fields keep track of where we are in tx/rx processing */
+ volatile rx_dscr *rxdscr_start; /* beginning of ring */
+ volatile rx_dscr *rxdscr_end; /* end of ring */
+ volatile rx_dscr *rxdscr_remove; /* next one we expect DMA to use */
+ volatile rx_dscr *rxdscr_add; /* next place to put a buffer */
+ int rxdscr_onring;
+
+ volatile tx_dscr *txdscr_start; /* beginning of ring */
+ volatile tx_dscr *txdscr_end; /* end of ring */
+ volatile tx_dscr *txdscr_remove; /* next one we will use for tx */
+ volatile tx_dscr *txdscr_add; /* next place to put a buffer */
+
+ cfe_devctx_t *devctx;
+
+ /* These fields describe the PHY */
+ int phy_addr;
+ int phy_check;
+ uint32_t phy_status;
+
+ /* Statistics */
+ uint32_t inpkts;
+ uint32_t outpkts;
+ uint32_t interrupts;
+ uint32_t rx_interrupts;
+ uint32_t tx_interrupts;
+ uint32_t bus_errors;
+} dp83815_softc;
+
+
+/* Entry to and exit from critical sections (currently relative to
+ interrupts only, not SMP) */
+
+#if CFG_INTERRUPTS
+#define CS_ENTER(sc) cfe_disable_irq(sc->irq)
+#define CS_EXIT(sc) cfe_enable_irq(sc->irq)
+#else
+#define CS_ENTER(sc) ((void)0)
+#define CS_EXIT(sc) ((void)0)
+#endif
+
+
+/* Driver parameterization */
+
+#define MAXRXDSCR 32
+#define MAXTXDSCR 32
+#define MINRXRING 8
+
+
+/* Prototypes */
+
+static void dp83815_ether_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+
+/* Address mapping macros */
+
+/* Note that PTR_TO_PHYS only works with 32-bit addresses, but then
+ so does the dp83815. */
+#define PTR_TO_PHYS(x) (K0_TO_PHYS((uintptr_t)(x)))
+#define PHYS_TO_PTR(a) ((uint8_t *)PHYS_TO_K0(a))
+
+/* All mappings through the PCI host bridge use match bits mode. */
+#define PHYS_TO_PCI(a) ((uint32_t) (a) | 0x20000000)
+#define PCI_TO_PHYS(a) ((uint32_t) (a) & 0x1FFFFFFF)
+
+#define PCI_TO_PTR(a) (PHYS_TO_PTR(PCI_TO_PHYS(a)))
+#define PTR_TO_PCI(x) (PHYS_TO_PCI(PTR_TO_PHYS(x)))
+
+#if __long64
+#define READCSR(sc,csr) \
+ (*((volatile uint32_t *) (PHYS_TO_XKSEG_UNCACHED((sc)->membase + (csr)))))
+
+#define WRITECSR(sc,csr,val) \
+ (*((volatile uint32_t *) \
+ (PHYS_TO_XKSEG_UNCACHED((sc)->membase + (csr)))) = (val))
+
+#else
+#define READCSR(sc,csr) \
+ (hs_read32(PHYS_TO_XKSEG_UNCACHED((sc)->membase + (csr))))
+
+#define WRITECSR(sc,csr,val) \
+ (hs_write32(PHYS_TO_XKSEG_UNCACHED((sc)->membase + (csr)), (val)))
+
+#endif
+
+#define RESET_ADAPTER(sc) \
+ { \
+ /* XXX */ \
+ }
+
+
+/* Debugging */
+
+static void
+dumpstat(dp83815_softc *sc)
+{
+ xprintf("-- CR = %08X CFG = %08x\n",
+ READCSR(sc, R_CR), READCSR(sc, R_CFG));
+}
+
+static void
+dumpcsrs(dp83815_softc *sc)
+{
+ int reg;
+
+ xprintf("-------------\n");
+ for (reg = 0; reg < R_MIBC; reg += 4) {
+ xprintf("CSR %02X = %08X\n", reg, READCSR(sc, reg));
+ }
+ xprintf("-------------\n");
+}
+
+
+/* Packet management */
+
+/* *********************************************************************
+ * ETH_ALLOC_PKT(sc)
+ *
+ * Allocate a packet from the free list.
+ *
+ * Input parameters:
+ * sc - eth structure
+ *
+ * Return value:
+ * pointer to packet structure, or NULL if none available
+ ********************************************************************* */
+static eth_pkt_t *
+eth_alloc_pkt(dp83815_softc *sc)
+{
+ eth_pkt_t *pkt;
+
+ CS_ENTER(sc);
+ pkt = (eth_pkt_t *) q_deqnext(&sc->freelist);
+ CS_EXIT(sc);
+ if (!pkt) return NULL;
+
+ pkt->buffer = pkt->data;
+ pkt->length = ETH_PKTBUF_LEN;
+ pkt->flags = 0;
+
+ return pkt;
+}
+
+
+/* *********************************************************************
+ * ETH_FREE_PKT(sc,pkt)
+ *
+ * Return a packet to the free list
+ *
+ * Input parameters:
+ * sc - sbmac structure
+ * pkt - packet to return
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void
+eth_free_pkt(dp83815_softc *sc, eth_pkt_t *pkt)
+{
+ CS_ENTER(sc);
+ q_enqueue(&sc->freelist, &pkt->next);
+ CS_EXIT(sc);
+}
+
+
+/* *********************************************************************
+ * ETH_INITFREELIST(sc)
+ *
+ * Initialize the buffer free list for this mac. The memory
+ * allocated to the free list is carved up and placed on a linked
+ * list of buffers for use by the mac.
+ *
+ * Input parameters:
+ * sc - eth structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void
+eth_initfreelist(dp83815_softc *sc)
+{
+ int idx;
+ uint8_t *ptr;
+ eth_pkt_t *pkt;
+
+ q_init(&sc->freelist);
+
+ ptr = sc->pktpool;
+ for (idx = 0; idx < ETH_PKTPOOL_SIZE; idx++) {
+ pkt = (eth_pkt_t *) ptr;
+ eth_free_pkt(sc, pkt);
+ ptr += ETH_PKTBUF_SIZE;
+ }
+}
+
+
+/* Utilities */
+
+static const char *
+dp83815_devname(dp83815_softc *sc)
+{
+ return (sc->devctx != NULL ? cfe_device_name(sc->devctx) : "eth?");
+}
+
+
+/* Descriptor ring management */
+
+static int
+dp83815_add_rcvbuf(dp83815_softc *sc, eth_pkt_t *pkt)
+{
+ volatile rx_dscr *rxd;
+ volatile rx_dscr *nextrxd;
+
+ rxd = sc->rxdscr_add;
+
+ /* Figure out where the next descriptor will go */
+ nextrxd = rxd+1;
+ if (nextrxd == sc->rxdscr_end) {
+ nextrxd = sc->rxdscr_start;
+ }
+
+ /*
+ * If the next one is the same as our remove pointer,
+ * the ring is considered full. (it actually has room for
+ * one more, but we reserve the remove == add case for "empty")
+ */
+ if (nextrxd == sc->rxdscr_remove) return -1;
+
+ rxd->rxd_bufptr = PTR_TO_PCI(pkt->buffer);
+ rxd->rxd_cmdsts = M_DES1_INTR | V_DES1_SIZE(ETH_PKTBUF_LEN);
+
+ /* success, advance the pointer */
+ sc->rxdscr_add = nextrxd;
+ CS_ENTER(sc);
+ sc->rxdscr_onring++;
+ CS_EXIT(sc);
+
+ return 0;
+}
+
+static void
+dp83815_fillrxring(dp83815_softc *sc)
+{
+ eth_pkt_t *pkt;
+
+ while (1) {
+ CS_ENTER(sc);
+ if (sc->rxdscr_onring >= MINRXRING) {
+ CS_EXIT(sc);
+ break;
+ }
+ CS_EXIT(sc);
+ pkt = eth_alloc_pkt(sc);
+ if (pkt == NULL) {
+ /* could not allocate a buffer */
+ break;
+ }
+ if (dp83815_add_rcvbuf(sc, pkt) != 0) {
+ /* could not add buffer to ring */
+ eth_free_pkt(sc, pkt);
+ break;
+ }
+ }
+}
+
+
+/* *********************************************************************
+ * DP83815_RX_CALLBACK(sc, pkt)
+ *
+ * Receive callback routine. This routine is invoked when a
+ * buffer queued for receives is filled. In this simple driver,
+ * all we do is add the packet to a per-MAC queue for later
+ * processing, and try to put a new packet in the place of the one
+ * that was removed from the queue.
+ *
+ * Input parameters:
+ * sc - interface
+ * ptk - packet context (eth_pkt structure)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void
+dp83815_rx_callback(dp83815_softc *sc, eth_pkt_t *pkt)
+{
+ if (MACPHYTER_DEBUG) show_packet('>', pkt); /* debug */
+
+ CS_ENTER(sc);
+ q_enqueue(&sc->rxqueue, &pkt->next);
+ CS_EXIT(sc);
+ sc->inpkts++;
+
+ dp83815_fillrxring(sc);
+}
+
+
+static void
+dp83815_procrxring(dp83815_softc *sc)
+{
+ volatile rx_dscr *rxd;
+ eth_pkt_t *pkt;
+ eth_pkt_t *newpkt;
+ uint32_t cmdsts;
+
+ for (;;) {
+ rxd = (volatile rx_dscr *) sc->rxdscr_remove;
+
+ cmdsts = rxd->rxd_cmdsts;
+ if ((cmdsts & M_DES1_OWN) == 0) {
+ /* end of ring, no more packets */
+ break;
+ }
+
+ pkt = ETH_PKT_BASE(PCI_TO_PTR(rxd->rxd_bufptr));
+ pkt->length = G_DES1_SIZE(cmdsts) - CRC_SIZE;
+
+ /* Drop error packets */
+ if (cmdsts & M_DES1_RX_ERRORS) {
+#if MACPHYTER_DEBUG
+ if (pkt->length >= MIN_ETHER_PACK - CRC_SIZE)
+ xprintf("%s: rx error %08X\n", dp83815_devname(sc), cmdsts);
+#endif
+ dp83815_add_rcvbuf(sc, pkt);
+ goto next;
+ }
+
+ /* Pass up the packet */
+ dp83815_rx_callback(sc, pkt);
+
+ /* put a buffer back on the ring to replace this one */
+ newpkt = eth_alloc_pkt(sc);
+ if (newpkt) dp83815_add_rcvbuf(sc, newpkt);
+
+next:
+ /* update the pointer, accounting for buffer wrap. */
+ rxd++;
+ if (rxd == sc->rxdscr_end)
+ rxd = sc->rxdscr_start;
+
+ sc->rxdscr_remove = (rx_dscr *) rxd;
+ CS_ENTER(sc);
+ sc->rxdscr_onring--;
+ CS_EXIT(sc);
+ }
+}
+
+
+static int
+dp83815_add_txbuf(dp83815_softc *sc, eth_pkt_t *pkt)
+{
+ volatile tx_dscr *txd;
+ volatile tx_dscr *nexttxd;
+
+ txd = sc->txdscr_add;
+
+ /* Figure out where the next descriptor will go */
+ nexttxd = (txd+1);
+ if (nexttxd == sc->txdscr_end) {
+ nexttxd = sc->txdscr_start;
+ }
+
+ /* If the next one is the same as our remove pointer,
+ the ring is considered full. (it actually has room for
+ one more, but we reserve the remove == add case for "empty") */
+
+ if (nexttxd == sc->txdscr_remove) return -1;
+
+ txd->txd_bufptr = PTR_TO_PCI(pkt->buffer);
+ txd->txd_cmdsts = M_DES1_INTR | M_DES1_OWN | V_DES1_SIZE(pkt->length);
+
+ /* success, advance the pointer */
+ sc->txdscr_add = nexttxd;
+
+ return 0;
+}
+
+
+static int
+dp83815_transmit(dp83815_softc *sc,eth_pkt_t *pkt)
+{
+ int rv;
+
+ if (MACPHYTER_DEBUG) show_packet('<', pkt); /* debug */
+
+ rv = dp83815_add_txbuf(sc, pkt);
+ sc->outpkts++;
+
+ WRITECSR(sc, R_CR, M_CR_TXE | M_CR_RXE);
+ return rv;
+}
+
+
+static void
+dp83815_proctxring(dp83815_softc *sc)
+{
+ volatile tx_dscr *txd;
+ eth_pkt_t *pkt;
+ uint32_t cmdsts;
+
+ for (;;) {
+ txd = (volatile tx_dscr *) sc->txdscr_remove;
+
+ if (txd == sc->txdscr_add) {
+ /* ring is empty, no buffers to process */
+ break;
+ }
+
+ cmdsts = txd->txd_cmdsts;
+ if (cmdsts & M_DES1_OWN) {
+ /* Reached a packet still being transmitted */
+ break;
+ }
+
+ /* Just free the packet */
+ pkt = ETH_PKT_BASE(PCI_TO_PTR(txd->txd_bufptr));
+ eth_free_pkt(sc, pkt);
+
+ /* update the pointer, accounting for buffer wrap. */
+ txd++;
+ if (txd == sc->txdscr_end)
+ txd = sc->txdscr_start;
+
+ sc->txdscr_remove = (tx_dscr *) txd;
+ }
+}
+
+
+static void
+dp83815_initrings(dp83815_softc *sc)
+{
+ volatile tx_dscr *txd, *txn;
+ volatile rx_dscr *rxd, *rxn;
+
+ /* Claim ownership of all descriptors for the driver */
+
+ for (txd = sc->txdscr_start; txd != sc->txdscr_end; txd++) {
+ txn = txd + 1;
+ if (txn == sc->txdscr_end) txn = sc->txdscr_start;
+ txd->txd_link = PTR_TO_PCI(txn);
+ txd->txd_cmdsts = 0;
+ txd->txd_pad = 0;
+ }
+ for (rxd = sc->rxdscr_start; rxd != sc->rxdscr_end; rxd++) {
+ rxn = rxd + 1;
+ if (rxn == sc->rxdscr_end) rxn = sc->rxdscr_start;
+ rxd->rxd_link = PTR_TO_PCI(rxn);
+ rxd->rxd_cmdsts = M_DES1_OWN;
+ rxd->rxd_pad = 0;
+ }
+
+ /* Init the ring pointers */
+
+ sc->txdscr_add = sc->txdscr_remove = sc->txdscr_start;
+ sc->rxdscr_add = sc->rxdscr_remove = sc->rxdscr_start;
+ sc->rxdscr_onring = 0;
+
+ /* Add stuff to the receive ring */
+
+ dp83815_fillrxring(sc);
+}
+
+
+static int
+dp83815_init(dp83815_softc *sc)
+{
+ /* Allocate descriptor rings */
+ sc->rxdscrmem = KMALLOC(MAXRXDSCR*sizeof(rx_dscr), sizeof(rx_dscr));
+ sc->txdscrmem = KMALLOC(MAXTXDSCR*sizeof(tx_dscr), sizeof(tx_dscr));
+
+ /* Allocate buffer pool */
+ sc->pktpool = KMALLOC(ETH_PKTPOOL_SIZE*ETH_PKTBUF_SIZE, CACHE_ALIGN);
+ eth_initfreelist(sc);
+ q_init(&sc->rxqueue);
+
+ /* Fill in pointers to the rings */
+ sc->rxdscr_start = (rx_dscr *) (sc->rxdscrmem);
+ sc->rxdscr_end = sc->rxdscr_start + MAXRXDSCR;
+ sc->rxdscr_add = sc->rxdscr_start;
+ sc->rxdscr_remove = sc->rxdscr_start;
+ sc->rxdscr_onring = 0;
+
+ sc->txdscr_start = (tx_dscr *) (sc->txdscrmem);
+ sc->txdscr_end = sc->txdscr_start + MAXTXDSCR;
+ sc->txdscr_add = sc->txdscr_start;
+ sc->txdscr_remove = sc->txdscr_start;
+
+ dp83815_initrings(sc);
+
+ return 0;
+}
+
+
+static void
+dp83815_resetrings(dp83815_softc *sc)
+{
+ volatile tx_dscr *txd;
+ volatile rx_dscr *rxd;
+ eth_pkt_t *pkt;
+
+ /* Free already-sent descriptors and buffers */
+ dp83815_proctxring(sc);
+
+ /* Free any pending but unsent */
+ txd = (volatile tx_dscr *) sc->txdscr_remove;
+ while (txd != sc->txdscr_add) {
+ txd->txd_cmdsts &=~ M_DES1_OWN;
+ pkt = ETH_PKT_BASE(PCI_TO_PTR(txd->txd_bufptr));
+ eth_free_pkt(sc, pkt);
+
+ txd++;
+ if (txd == sc->txdscr_end)
+ txd = sc->txdscr_start;
+ }
+ sc->txdscr_add = sc->txdscr_remove;
+
+ /* Discard any received packets as well as all free buffers */
+ rxd = (volatile rx_dscr *) sc->rxdscr_remove;
+ while (rxd != sc->rxdscr_add) {
+ rxd->rxd_cmdsts |= M_DES1_OWN;
+ pkt = ETH_PKT_BASE(PCI_TO_PTR(rxd->rxd_bufptr));
+ eth_free_pkt(sc, pkt);
+
+ rxd++;
+ if (rxd == sc->rxdscr_end)
+ rxd = sc->rxdscr_start;
+ CS_ENTER(sc);
+ sc->rxdscr_onring--;
+ CS_EXIT(sc);
+ }
+
+ /* Reestablish the initial state. */
+ dp83815_initrings(sc);
+}
+
+
+#if 0 /* XXX Multicast filtering not yet implemented. */
+/* CRCs */
+
+#define IEEE_CRC32_POLY 0xEDB88320UL /* CRC-32 Poly -- either endian */
+
+static uint32_t
+dp83815_crc32(const uint8_t *databuf, unsigned int datalen)
+{
+ unsigned int idx, bit, data;
+ uint32_t crc;
+
+ crc = 0xFFFFFFFFUL;
+ for (idx = 0; idx < datalen; idx++)
+ for (data = *databuf++, bit = 0; bit < 8; bit++, data >>= 1)
+ crc = (crc >> 1) ^ (((crc ^ data) & 1) ? IEEE_CRC32_POLY : 0);
+ return crc;
+}
+
+#define dp83815_mchash(mca) (dp83815_crc32((mca), 6) & 0x1FF)
+#endif
+
+
+#if MACPHYTER_TEST
+/* EEPROM access */
+
+/* Current NICs use the EEPROM auto-load feature and there is no need
+ for explicit EEPROM access. The following routines are included
+ for future applications and have been tested (Netgear FA311). */
+
+/****************************************************************************
+ * dp83815_spin(sc, ns)
+ *
+ * Spin for a short interval (nominally in nanoseconds)
+ *
+ * Input Parameters: ns - minimum required nsec.
+ *
+ * The delay loop uses uncached PCI reads, each of which requires
+ * at least 3 PCI bus clocks (45 ns at 66 MHz) to complete. The
+ * actual delay will be longer (much longer if preempted).
+ ***************************************************************************/
+
+#define PCI_MIN_DELAY 45
+
+static void
+dp83815_spin(dp83815_softc *sc, long nanoseconds)
+{
+ long delay;
+ volatile uint32_t t;
+
+ for (delay = nanoseconds; delay > 0; delay -= PCI_MIN_DELAY)
+ t = READCSR(sc, R_SRR);
+}
+
+
+/*
+ * The recommended EEPROM is the NM9306.
+ * Delays below are chosen to meet specs for NS93C64 (slow M variant).
+ * Current parts are faster.
+ * Reference: NS Memory Data Book, 1994
+ */
+
+#define EEPROM_SIZE (2*0x0C)
+#define EEPROM_MAX_CYCLES 32
+
+#define EEPROM_CMD_BITS 3
+#define EEPROM_ADDR_BITS 6
+
+#define K_EEPROM_READ_CMD 06
+#define K_EEPROM_WRITE_CMD 05
+
+#define EEPROM_CRC_INDEX (EEPROM_SIZE-2)
+
+#define EEPROM_WORD(rom,offset) ((rom)[offset] | ((rom)[offset+1] << 8))
+
+static void
+eeprom_idle_state(dp83815_softc *sc)
+{
+ uint32_t ctrl;
+ unsigned int i;
+
+ ctrl = READCSR(sc, R_MEAR);
+
+ ctrl |= M_MEAR_EESEL;
+ WRITECSR(sc, R_MEAR, ctrl);
+ dp83815_spin(sc, 100); /* CS setup (Tcss=100) */
+
+ /* Run the clock through the maximum number of pending read cycles */
+ for (i = 0; i < EEPROM_MAX_CYCLES*2; i++) {
+ ctrl ^= M_MEAR_EECLK;
+ WRITECSR(sc, R_MEAR, ctrl);
+ dp83815_spin(sc, 1000); /* SK period (Fsk=0.5MHz) */
+ }
+
+ /* Deassert EEPROM Chip Select */
+ ctrl &=~ M_MEAR_EESEL;
+ WRITECSR(sc, R_MEAR, ctrl);
+ dp83815_spin(sc, 50); /* CS recovery (Tsks=50) */
+}
+
+static void
+eeprom_send_command_bit(dp83815_softc *sc, unsigned int data)
+{
+ uint32_t ctrl;
+
+ ctrl = READCSR(sc, R_MEAR);
+
+ /* Place the data bit on the bus */
+ if (data == 1)
+ ctrl |= M_MEAR_EEDI;
+ else
+ ctrl &=~ M_MEAR_EEDI;
+
+ WRITECSR(sc, R_MEAR, ctrl);
+ dp83815_spin(sc, 360); /* setup: Tdis=200 */
+
+ /* Now clock the data into the EEPROM */
+ WRITECSR(sc, R_MEAR, ctrl | M_MEAR_EECLK);
+ dp83815_spin(sc, 900); /* clock high, Tskh=500 */
+ WRITECSR(sc, R_MEAR, ctrl);
+ dp83815_spin(sc, 450); /* clock low, Tskl=250 */
+
+ /* Now clear the data bit */
+ ctrl &=~ M_MEAR_EEDI; /* data invalid, Tidh=20 for SK^ */
+ WRITECSR(sc, R_MEAR, ctrl);
+ dp83815_spin(sc, 270); /* min cycle, 1/Fsk=2000 */
+}
+
+static uint16_t
+eeprom_read_bit(dp83815_softc *sc)
+{
+ uint32_t ctrl;
+
+ ctrl = READCSR(sc, R_MEAR);
+
+ /* Generate a clock cycle before doing a read */
+ WRITECSR(sc, R_MEAR, ctrl | M_MEAR_EECLK); /* rising edge */
+ dp83815_spin(sc, 1000); /* clock high, Tskh=500, Tpd=1000 */
+ WRITECSR(sc, R_MEAR, ctrl); /* falling edge */
+ dp83815_spin(sc, 1000); /* clock low, 1/Fsk=2000 */
+
+ ctrl = READCSR(sc, R_MEAR);
+ return ((ctrl & M_MEAR_EEDO) != 0 ? 1 : 0);
+}
+
+#define CMD_BIT_MASK (1 << (EEPROM_CMD_BITS+EEPROM_ADDR_BITS-1))
+
+static uint16_t
+eeprom_read_word(dp83815_softc *sc, unsigned int index)
+{
+ uint16_t command, word;
+ uint32_t ctrl;
+ unsigned int i;
+
+ ctrl = READCSR(sc, R_MEAR) | M_MEAR_EESEL;
+
+ /* Assert the EEPROM CS line */
+ WRITECSR(sc, R_MEAR, ctrl);
+ dp83815_spin(sc, 100); /* CS setup, Tcss = 100 */
+
+ /* Send the read command to the EEPROM */
+ command = (K_EEPROM_READ_CMD << EEPROM_ADDR_BITS) | index;
+ for (i = 0; i < EEPROM_CMD_BITS+EEPROM_ADDR_BITS; i++) {
+ eeprom_send_command_bit(sc, (command & CMD_BIT_MASK) != 0 ? 1 : 0);
+ command <<= 1;
+ }
+
+ /* Now read the bits from the EEPROM (MSB first) */
+ word = 0;
+ for (i = 0; i < 16; ++i) {
+ word <<= 1;
+ word |= eeprom_read_bit(sc);
+ }
+
+ /* Clear the EEPROM CS Line, CS hold, Tcsh = 0 */
+ WRITECSR(sc, R_MEAR, ctrl &~ M_MEAR_EESEL);
+
+ return word;
+}
+
+
+/****************************************************************************
+ * eeprom_checksum()
+ *
+ * Calculate the checksum of the EEPROM and return it. See Section
+ * 4.2.4 for the algorithm.
+ ***************************************************************************/
+
+static uint16_t
+eeprom_checksum(const uint8_t rom[])
+{
+ uint16_t sum;
+ int i;
+
+ sum = 0;
+ for (i = 0; i < EEPROM_SIZE-1; i++)
+ sum += rom[i];
+ sum ^= 0xFF;
+ return (((sum + 1) & 0xFF) << 8) | 0x55;
+}
+
+
+/****************************************************************************
+ * eeprom_read_all(sc, uint8_t dest)
+ *
+ * Read the entire EEPROM into the srom array
+ *
+ * Input parameters:
+ * sc - dp83815 state
+ ***************************************************************************/
+
+static int
+eeprom_read_all(dp83815_softc *sc, uint8_t dest[])
+{
+ int i;
+ uint16_t cksum, temp;
+
+ WRITECSR(sc, R_MEAR, M_MEAR_EESEL);
+
+ eeprom_idle_state(sc);
+
+ for (i = 0; i < EEPROM_SIZE/2; i++) {
+ temp = eeprom_read_word(sc, i);
+ dest[2*i] = temp & 0xFF;
+ dest[2*i+1] = temp >> 8;
+ }
+
+ WRITECSR(sc, R_MEAR, 0); /* CS hold, Tcsh=0 */
+
+ cksum = eeprom_checksum(dest);;
+ if (cksum != EEPROM_WORD(dest, EEPROM_CRC_INDEX)) {
+ xprintf("%s: Invalid EEPROM CHECKSUM, calc %04x, stored %04x\n",
+ dp83815_devname(sc),
+ cksum, EEPROM_WORD(dest, EEPROM_CRC_INDEX));
+ return 0/*-1*/;
+ }
+ return 0;
+}
+
+static int
+eeprom_read_addr(const uint8_t rom[], uint8_t buf[])
+{
+ uint16_t s;
+ unsigned offset, mask;
+ int i, j;
+
+ if (eeprom_checksum(rom) != EEPROM_WORD(rom, EEPROM_SIZE-2))
+ return -1;
+
+ s = 0;
+ offset = 2*6; mask = 0x1;
+ i = j = 0;
+ do {
+ s >>= 1;
+ if ((EEPROM_WORD(rom, offset) & mask) != 0) s |= 0x8000;
+ mask >>= 1;
+ if (mask == 0) {
+ offset +=2; mask = 0x8000;
+ }
+ i++;
+ if (i % 16 == 0) {
+ buf[j++] = s & 0xFF;
+ buf[j++] = s >> 8;
+ s = 0;
+ }
+ } while (i < ENET_ADDR_LEN*8);
+
+ return 0;
+}
+#endif /* MACPHYTER_TEST */
+
+#if 0
+static void
+eeprom_dump(uint8_t srom[])
+{
+ int i;
+
+ xprintf("DP83815: EEPROM data:");
+ for (i = 0; i < EEPROM_SIZE; i++) {
+ if (i % 16 == 0)
+ xprintf("\n %02x: ", i);
+ xprintf(" %02x", srom[i]);
+ }
+ xprintf("\n");
+}
+#else
+#define eeprom_dump(srom)
+#endif
+
+
+static int
+dp83815_get_pm_addr(dp83815_softc *sc, uint8_t buf[])
+{
+ uint32_t rfcr;
+ unsigned rfaddr;
+ unsigned i;
+ uint32_t rfdata;
+
+ rfcr = READCSR(sc, R_RFCR);
+ rfaddr = K_RFCR_PMATCH_ADDR;
+
+ for (i = 0; i < ENET_ADDR_LEN/2; i++) {
+ rfcr &=~ M_RFCR_RFADDR;
+ rfcr |= V_RFCR_RFADDR(rfaddr);
+ WRITECSR(sc, R_RFCR, rfcr);
+ rfdata = READCSR(sc, R_RFDR);
+ buf[2*i] = rfdata & 0xFF;
+ buf[2*i+1] = (rfdata >> 8) & 0xFF;
+ rfaddr += 2;
+ }
+
+ return 0;
+}
+
+
+#if MACPHYTER_TEST
+/* MII access */
+
+/* Current NICs use the internal PHY, which can be accessed more
+ simply via internal registers. The following routines are
+ primarily for management access to an external PHY and are retained
+ for future applications. They have been tested on a Netgear FA311. */
+
+/****************************************************************************
+ * MII access utility routines
+ ***************************************************************************/
+
+/* MII clock limited to 2.5 MHz (DP83815 allows 25 MHz), transactions
+ end with MDIO tristated */
+
+static void
+mii_write_bits(dp83815_softc *sc, uint32_t data, unsigned int count)
+{
+ uint32_t ctrl;
+ uint32_t bitmask;
+
+ ctrl = READCSR(sc, R_MEAR) & ~M_MEAR_MDC;
+ ctrl |= M_MEAR_MDDIR;
+
+ for (bitmask = 1 << (count-1); bitmask != 0; bitmask >>= 1) {
+ ctrl &=~ M_MEAR_MDIO;
+ if ((data & bitmask) != 0) ctrl |= M_MEAR_MDIO;
+ WRITECSR(sc, R_MEAR, ctrl);
+
+ dp83815_spin(sc, 2000); /* setup */
+ WRITECSR(sc, R_MEAR, ctrl | M_MEAR_MDC);
+ dp83815_spin(sc, 2000); /* hold */
+ WRITECSR(sc, R_MEAR, ctrl);
+ }
+}
+
+static void
+mii_turnaround(dp83815_softc *sc)
+{
+ uint32_t ctrl;
+
+ ctrl = READCSR(sc, R_MEAR) &~ M_MEAR_MDDIR;
+
+ /* stop driving data */
+ WRITECSR(sc, R_MEAR, ctrl);
+ dp83815_spin(sc, 2000); /* setup */
+ WRITECSR(sc, R_MEAR, ctrl | M_MEAR_MDC);
+ dp83815_spin(sc, 2000); /* clock high */
+ WRITECSR(sc, R_MEAR, ctrl);
+
+ /* read back and check for 0 here? */
+}
+
+/****************************************************************************
+ * mii_read_register
+ *
+ * This routine reads a register from the PHY chip using the MII
+ * serial management interface.
+ *
+ * Input parameters:
+ * index - index of register to read (0-31)
+ *
+ * Return value:
+ * word read from register
+ ***************************************************************************/
+
+static uint16_t
+mii_read_register(dp83815_softc *sc, unsigned int index)
+{
+ /* Send the command and address to the PHY. The sequence is
+ a synchronization sequence (32 1 bits)
+ a "start" command (2 bits)
+ a "read" command (2 bits)
+ the PHY addr (5 bits)
+ the register index (5 bits)
+ */
+ uint32_t ctrl;
+ uint16_t word;
+ int i;
+
+ mii_write_bits(sc, 0xFF, 8);
+ mii_write_bits(sc, 0xFFFFFFFF, 32);
+ mii_write_bits(sc, MII_COMMAND_START, 2);
+ mii_write_bits(sc, MII_COMMAND_READ, 2);
+ mii_write_bits(sc, sc->phy_addr, 5);
+ mii_write_bits(sc, index, 5);
+
+ mii_turnaround(sc);
+
+ ctrl = READCSR(sc, R_MEAR) &~ (M_MEAR_MDC | M_MEAR_MDDIR);
+ word = 0;
+
+ for (i = 0; i < 16; i++) {
+ WRITECSR(sc, R_MEAR, ctrl);
+ dp83815_spin(sc, 2000); /* clock width low */
+ WRITECSR(sc, R_MEAR, ctrl | M_MEAR_MDC);
+ dp83815_spin(sc, 2000); /* clock width high */
+ WRITECSR(sc, R_MEAR, ctrl);
+ dp83815_spin(sc, 1000); /* output delay */
+ word <<= 1;
+ if ((READCSR(sc, R_MEAR) & M_MEAR_MDIO) != 0)
+ word |= 0x0001;
+ }
+
+ return word;
+
+ /* reset to output mode? */
+}
+
+/****************************************************************************
+ * mii_write_register
+ *
+ * This routine writes a register in the PHY chip using the MII
+ * serial management interface.
+ *
+ * Input parameters:
+ * index - index of register to write (0-31)
+ * value - word to write
+ ***************************************************************************/
+
+static void
+mii_write_register(dp83815_softc *sc, unsigned int index, uint16_t value)
+{
+ mii_write_bits(sc, 0xFF, 8);
+ mii_write_bits(sc, 0xFFFFFFFF, 32);
+ mii_write_bits(sc, MII_COMMAND_START, 2);
+ mii_write_bits(sc, MII_COMMAND_WRITE, 2);
+ mii_write_bits(sc, sc->phy_addr, 5);
+ mii_write_bits(sc, index, 5);
+ mii_write_bits(sc, MII_COMMAND_ACK, 2);
+ mii_write_bits(sc, value, 16);
+
+ /* reset to input mode? */
+}
+
+
+static int
+mii_probe(dp83815_softc *sc)
+{
+ int i;
+ uint16_t id1, id2;
+
+ /* Empirically, bit-banged access will return register 0 of the
+ integrated PHY for all registers of all unpopulated PHY
+ addresses. */
+ for (i = 0; i < 32; i++) {
+ sc->phy_addr = i;
+ id1 = mii_read_register(sc, MII_PHYIDR1);
+ id2 = mii_read_register(sc, MII_PHYIDR2);
+ if ((id1 != 0x0000 && id1 != 0xFFFF) ||
+ (id2 != 0x0000 && id2 != 0xFFFF)) {
+ if (id1 != id2) return 0;
+ }
+ }
+ return -1;
+}
+
+#if 0
+#define OUI_NAT_SEMI 0x080017
+#define IDR_NAT_SEMI 0x080017 /* NSC does not bit-reverse each byte */
+#define PART_83815 0x02
+
+static void
+mii_dump(dp83815_softc *sc, const char *label)
+{
+ int i;
+ uint16_t r;
+ uint32_t idr, part;
+
+ xprintf("%s\n", label);
+ idr = 0;
+ for (i = 0; i <= 6; ++i) {
+ r = mii_read_register(sc, i);
+ xprintf("MII_REG%02x: %04x\n", i, r);
+ if (i == MII_PHYIDR1) {
+ idr |= r << 6;
+ }
+ else if (i == MII_PHYIDR2) {
+ idr |= (r >> 10) & 0x3F;
+ part = (r >> 4) & 0x3F;
+ }
+ }
+ if (idr == IDR_NAT_SEMI && part == PART_83815) {
+ r = mii_read_register(sc, 7);
+ xprintf("MII_REG%02x: %04x\n", i, r);
+ for (i = 0x10; i <= 0x16; ++i) {
+ r = mii_read_register(sc, i);
+ xprintf("MII_REG%02x: %04x\n", i, r);
+ }
+ for (i = 0x19; i <= 0x1A; ++i) {
+ r = mii_read_register(sc, i);
+ xprintf("MII_REG%02x: %04x\n", i, r);
+ }
+ }
+}
+#else
+#define mii_dump(sc,label)
+#endif
+
+
+/* The following functions are suitable for explicit MII access. */
+
+static void
+mii_set_speed(dp83815_softc *sc, int speed)
+{
+ uint16_t control;
+
+ control = mii_read_register(sc, MII_BMCR);
+
+ control &=~ (BMCR_ANENABLE | BMCR_RESTARTAN);
+ mii_write_register(sc, MII_BMCR, control);
+ control &=~ (BMCR_SPEED0 | BMCR_SPEED1 | BMCR_DUPLEX);
+
+ switch (speed) {
+ case ETHER_SPEED_10HDX:
+ default:
+ break;
+ case ETHER_SPEED_10FDX:
+ control |= BMCR_DUPLEX;
+ break;
+ case ETHER_SPEED_100HDX:
+ control |= BMCR_SPEED100;
+ break;
+ case ETHER_SPEED_100FDX:
+ control |= BMCR_SPEED100 | BMCR_DUPLEX ;
+ break;
+ }
+
+ mii_write_register(sc, MII_BMCR, control);
+}
+
+static void
+mii_autonegotiate(dp83815_softc *sc)
+{
+ uint16_t control, status, cap;
+ int timeout;
+ int linkspeed;
+
+ linkspeed = ETHER_SPEED_UNKNOWN;
+
+ /* Read twice to clear latching bits */
+ status = mii_read_register(sc, MII_BMSR);
+ status = mii_read_register(sc, MII_BMSR);
+ mii_dump(sc, "query PHY");
+
+ if ((status & (BMSR_AUTONEG | BMSR_LINKSTAT)) ==
+ (BMSR_AUTONEG | BMSR_LINKSTAT))
+ control = mii_read_register(sc, MII_BMCR);
+ else {
+ /* reset the PHY */
+ mii_write_register(sc, MII_BMCR, BMCR_RESET);
+ timeout = 3*CFE_HZ;
+ for (;;) {
+ control = mii_read_register(sc, MII_BMCR);
+ if ((control && BMCR_RESET) == 0 || timeout <= 0)
+ break;
+ cfe_sleep(CFE_HZ/2);
+ timeout -= CFE_HZ/2;
+ }
+ if ((control & BMCR_RESET) != 0) {
+ xprintf("%s: PHY reset failed\n", dp83815_devname(sc));
+ return;
+ }
+
+ status = mii_read_register(sc, MII_BMSR);
+ cap = ((status >> 6) & (ANAR_TXFD | ANAR_TXHD | ANAR_10FD | ANAR_10HD))
+ | PSB_802_3;
+ mii_write_register(sc, MII_ANAR, cap);
+ control |= (BMCR_ANENABLE | BMCR_RESTARTAN);
+ mii_write_register(sc, MII_BMCR, control);
+
+ timeout = 3*CFE_HZ;
+ for (;;) {
+ status = mii_read_register(sc, MII_BMSR);
+ if ((status & BMSR_ANCOMPLETE) != 0 || timeout <= 0)
+ break;
+ cfe_sleep(CFE_HZ/2);
+ timeout -= CFE_HZ/2;
+ }
+ mii_dump(sc, "done PHY");
+ }
+
+ xprintf("%s: Link speed: ", dp83815_devname(sc));
+ if ((status & BMSR_ANCOMPLETE) != 0) {
+ /* A link partner was negogiated... */
+
+ uint16_t remote = mii_read_register(sc, MII_ANLPAR);
+
+ if ((remote & ANLPAR_TXFD) != 0) {
+ xprintf("100BaseT FDX\n");
+ linkspeed = ETHER_SPEED_100FDX;
+ }
+ else if ((remote & ANLPAR_TXHD) != 0) {
+ xprintf("100BaseT HDX\n");
+ linkspeed = ETHER_SPEED_100HDX;
+ }
+ else if ((remote & ANLPAR_10FD) != 0) {
+ xprintf("10BaseT FDX\n");
+ linkspeed = ETHER_SPEED_10FDX;
+ }
+ else if ((remote & ANLPAR_10HD) != 0) {
+ xprintf("10BaseT HDX\n");
+ linkspeed = ETHER_SPEED_10HDX;
+ }
+ }
+ else {
+ /* no link partner negotiation */
+ control &=~ (BMCR_ANENABLE | BMCR_RESTARTAN);
+ mii_write_register(sc, MII_BMCR, control);
+ xprintf("10BaseT HDX (assumed)\n");
+ linkspeed = ETHER_SPEED_10HDX;
+ if ((status & BMSR_LINKSTAT) == 0)
+ mii_write_register(sc, MII_BMCR, control);
+ mii_set_speed(sc, linkspeed);
+ }
+
+ status = mii_read_register(sc, MII_BMSR); /* clear latching bits */
+ mii_dump(sc, "final PHY");
+}
+#endif /* MACPHYTER_TEST */
+
+
+static void
+dp83815_phyupdate(dp83815_softc *sc, uint32_t status)
+{
+ xprintf("%s: Link speed: ", dp83815_devname(sc));
+ if ((status & M_CFG_LNKSTS) != 0) {
+ switch (status & (M_CFG_SPEED100 | M_CFG_FDUP)) {
+ case (M_CFG_SPEED100 | M_CFG_FDUP):
+ sc->linkspeed = ETHER_SPEED_100FDX;
+ xprintf("100BaseT FDX\n");
+ break;
+ case (M_CFG_SPEED100):
+ sc->linkspeed = ETHER_SPEED_100HDX;
+ xprintf("100BaseT HDX\n");
+ break;
+ case (M_CFG_FDUP):
+ sc->linkspeed = ETHER_SPEED_10FDX;
+ xprintf("10BaseT FDX\n");
+ break;
+ default:
+ sc->linkspeed = ETHER_SPEED_10HDX;
+ xprintf("10BaseT HDX\n");
+ break;
+ }
+ if ((status & M_CFG_SPEED100) != 0) {
+ uint32_t t;
+
+ /* This is a reputed fix that improves 100BT rx
+ performance on short cables with "a small number"
+ of DP83815 chips. It comes from Bruce at NatSemi
+ via the Soekris support web page (see appended
+ note). */
+
+ WRITECSR(sc, R_PGSEL, 0x0001);
+ (void)READCSR(sc, R_PGSEL); /* push */
+ t = READCSR(sc, R_DSPCFG);
+ WRITECSR(sc, R_DSPCFG, (t & 0xFFF) | 0x1000);
+ cfe_sleep(1);
+ t = READCSR(sc, R_TSTDAT) & 0xFF;
+ if ((t & 0x0080) == 0 || ((t > 0x00D8) && (t <= 0x00FF))) {
+ WRITECSR(sc, R_TSTDAT, 0x00E8);
+ t = READCSR(sc, R_DSPCFG);
+ WRITECSR(sc, R_DSPCFG, t | 0x0020);
+ }
+ WRITECSR(sc, R_PGSEL, 0);
+ }
+ if ((status & M_CFG_FDUP) != (sc->phy_status & M_CFG_FDUP)) {
+ uint32_t txcfg;
+
+ txcfg = READCSR(sc, R_TXCFG);
+ if (status & M_CFG_FDUP)
+ txcfg |= M_TXCFG_CSI;
+ else
+ txcfg &= ~M_TXCFG_CSI;
+ WRITECSR(sc, R_RXCFG, txcfg);
+ }
+ }
+ else {
+ xprintf("Unknown\n");
+ }
+
+ sc->phy_status = status;
+}
+
+static void
+dp83815_hwinit(dp83815_softc *sc)
+{
+ if (sc->state == eth_state_uninit) {
+ uint32_t cfg;
+ uint32_t txcfg, rxcfg;
+ uint32_t ready;
+ int timeout;
+
+ /* RESET_ADAPTER(sc); */
+ sc->state = eth_state_off;
+ sc->bus_errors = 0;
+
+ cfg = READCSR(sc, R_CFG);
+ cfg |= M_CFG_BEM; /* We will use match bits */
+ WRITECSR(sc, R_CFG, cfg);
+
+ sc->phy_status = 0;
+ dp83815_phyupdate(sc, cfg & M_CFG_LNKSUMMARY);
+
+ txcfg = READCSR(sc, R_TXCFG);
+ txcfg |= M_TXCFG_ATP;
+ /* XXX fix up FLTH, DRTH? */
+ WRITECSR(sc, R_TXCFG, txcfg);
+
+ rxcfg = READCSR(sc, R_RXCFG);
+ /* Set an aggressive rx drain threshhold of 16 (2*8) bytes */
+ rxcfg &= ~M_RXCFG_DRTH;
+ rxcfg |= V_RXCFG_DRTH(2);
+ WRITECSR(sc, R_RXCFG, rxcfg);
+
+#if MACPHYTER_TEST
+ {
+ uint8_t srom[EEPROM_SIZE];
+ uint8_t addr[ENET_ADDR_LEN];
+
+ eeprom_read_all(sc, srom);
+ eeprom_dump(srom);
+ xprintf(" checksum %04x\n", eeprom_checksum(srom));
+ if (eeprom_read_addr(srom, addr) == 0)
+ xprintf(" addr: %02x-%02x-%02x-%02x-%02x-%02x\n",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+
+ mii_probe(sc);
+ xprintf("MII address %02x\n", sc->phy_addr);
+ mii_dump(sc, "DP83815 PHY:");
+ (void)mii_autonegotiate;
+ }
+#endif /* MACPHYTER_TEST */
+
+ /* XXX fix up rx filtering here. We are relying on the EEPROM. */
+
+ /* XXX This is inappropriate on a restart. */
+ timeout = 2*CFE_HZ;
+ ready = 0;
+ for (;;) {
+ ready |= READCSR(sc, R_ISR);
+ if ((ready & (M_INT_TXRCMP | M_INT_RXRCMP))
+ == (M_INT_TXRCMP | M_INT_RXRCMP) || timeout <= 0)
+ break;
+ cfe_sleep(CFE_HZ/10);
+ timeout -= CFE_HZ/10;
+ }
+ if ((ready & M_INT_TXRCMP) == 0)
+ xprintf("%s: tx reset failed\n", dp83815_devname(sc));
+ if ((ready & M_INT_RXRCMP) == 0)
+ xprintf("%s: rx reset failed\n", dp83815_devname(sc));
+ }
+}
+
+static void
+dp83815_setspeed(dp83815_softc *sc, int speed)
+{
+ /* XXX Not yet implemented - autonegotiation only. */
+}
+
+static void
+dp83815_setloopback(dp83815_softc *sc, int mode)
+{
+ /* XXX Not yet implemented. */
+}
+
+
+static void
+dp83815_isr(void *arg)
+{
+ dp83815_softc *sc = (dp83815_softc *)arg;
+ uint32_t status;
+ uint32_t isr;
+
+#if IPOLL
+ sc->interrupts++;
+#endif
+
+ for (;;) {
+
+ /* Read (and clear) the interrupt status. */
+ isr = READCSR(sc, R_ISR);
+ status = isr & sc->intmask;
+
+ /* if there are no more interrupts, leave now. */
+ if (status == 0) break;
+
+ /* Now, test each unmasked bit in the interrupt register and
+ handle each interrupt type appropriately. */
+
+ if (status & (M_INT_RTABT | M_INT_RMABT)) {
+ WRITECSR(sc, R_IER, 0);
+
+ xprintf("%s: bus error\n", dp83815_devname(sc));
+ dumpstat(sc);
+ sc->bus_errors++;
+ if (sc->bus_errors >= 2) {
+ dumpcsrs(sc);
+ RESET_ADAPTER(sc);
+ sc->state = eth_state_off;
+ sc->bus_errors = 0;
+ }
+#if IPOLL
+ else
+ WRITECSR(sc, R_IMR, sc->intmask);
+#endif
+ }
+
+ if (status & M_INT_RXDESC) {
+#if IPOLL
+ sc->rx_interrupts++;
+#endif
+ dp83815_procrxring(sc);
+ }
+
+ if (status & M_INT_TXDESC) {
+#if IPOLL
+ sc->tx_interrupts++;
+#endif
+ dp83815_proctxring(sc);
+ }
+
+ if (status & (M_INT_TXURN | M_INT_RXORN)) {
+ if (status & M_INT_TXURN) {
+ xprintf("%s: tx underrun, %08x\n", dp83815_devname(sc), isr);
+ /* XXX Try to restart */
+ }
+ if (status & M_INT_RXORN) {
+ xprintf("%s: tx overrun, %08x\n", dp83815_devname(sc), isr);
+ /* XXX Try to restart */
+ }
+ }
+
+ if (status & M_INT_PHY) {
+ sc->intmask &= ~ M_INT_PHY;
+ WRITECSR(sc, R_IMR, sc->intmask);
+ (void)READCSR(sc, R_MISR); /* Clear at PHY */
+ sc->phy_check = 1;
+ }
+
+ }
+}
+
+static void
+dp83815_checkphy(dp83815_softc *sc)
+{
+ uint32_t cfg;
+ uint32_t status;
+
+ (void)READCSR(sc, R_MISR); /* Clear at PHY */
+ cfg = READCSR(sc, R_CFG);
+ status = cfg & M_CFG_LNKSUMMARY;
+ if (status != sc->phy_status) {
+ /* XXX Can we really do the phy update with active rx and tx? */
+ dp83815_phyupdate(sc, status);
+ }
+
+ sc->intmask |= M_INT_PHY;
+ WRITECSR(sc, R_IMR, sc->intmask);
+}
+
+
+static void
+dp83815_start(dp83815_softc *sc)
+{
+ dp83815_hwinit(sc);
+
+ /* Set up loopback here */
+
+ sc->intmask = 0;
+ WRITECSR(sc, R_IER, 0); /* no interrupts */
+ WRITECSR(sc, R_IMR, 0);
+ (void)READCSR(sc, R_ISR); /* clear any pending */
+
+ sc->phy_status = READCSR(sc, R_CFG) & M_CFG_LNKSUMMARY;
+ sc->phy_check = 0;
+
+ sc->intmask = M_INT_RXDESC | M_INT_TXDESC;
+ sc->intmask |= M_INT_RTABT | M_INT_RMABT | M_INT_RXORN | M_INT_TXURN;
+ sc->intmask |= M_INT_PHY;
+
+#if IPOLL
+ cfe_request_irq(sc->irq, dp83815_isr, sc, CFE_IRQ_FLAGS_SHARED, 0);
+ WRITECSR(sc, R_IMR, sc->intmask);
+ WRITECSR(sc, R_IER, M_IER_IE);
+#endif
+
+ (void)READCSR(sc, R_MISR); /* clear any pending */
+ WRITECSR(sc, R_MISR, MISR_MSKJAB | MISR_MSKRF | MISR_MSKFHF | MISR_MSKRHF);
+ WRITECSR(sc, R_MICR, MICR_INTEN);
+
+ WRITECSR(sc, R_TXDP, PTR_TO_PCI(sc->txdscr_start));
+ WRITECSR(sc, R_RXDP, PTR_TO_PCI(sc->rxdscr_start));
+
+ WRITECSR(sc, R_MIBC, M_MIBC_ACLR); /* zero hw MIB counters */
+
+ WRITECSR(sc, R_CR, M_CR_TXE | M_CR_RXE);
+ sc->state = eth_state_on;
+}
+
+static void
+dp83815_stop(dp83815_softc *sc)
+{
+ uint32_t status;
+ int count;
+
+ /* Make sure that no further interrutps will be processed. */
+ sc->intmask = 0;
+ WRITECSR(sc, R_IER, 0);
+ WRITECSR(sc, R_IMR, 0);
+
+#if IPOLL
+ (void)READCSR(sc, R_IER); /* Push */
+ cfe_free_irq(sc->irq, 0);
+#endif
+
+ WRITECSR(sc, R_CR, M_CR_TXD | M_CR_RXD);
+
+ /* wait for any DMA activity to terminate */
+ for (count = 0; count <= 13; count++) {
+ status = READCSR(sc, R_CR);
+ if ((status & (M_CR_TXE | M_CR_RXE)) == 0)
+ break;
+ cfe_sleep(CFE_HZ/10);
+ }
+ if (count > 13) {
+ xprintf("%s: idle state not achieved\n", dp83815_devname(sc));
+ dumpstat(sc);
+ RESET_ADAPTER(sc);
+ sc->state = eth_state_uninit;
+#if 1
+ sc->linkspeed = ETHER_SPEED_AUTO;
+#endif
+ }
+#if 0 /* XXX Not yet implemented. */
+ else if (sc->loopback != ETHER_LOOPBACK_OFF) {
+ dp83815_setloopback(sc, ETHER_LOOPBACK_OFF);
+ }
+#endif
+
+ (void)READCSR(sc, R_ISR); /* Clear any stragglers. */
+}
+
+
+/* *********************************************************************
+ * ETH_PARSE_XDIGIT(c)
+ *
+ * Parse a hex digit, returning its value
+ *
+ * Input parameters:
+ * c - character
+ *
+ * Return value:
+ * hex value, or -1 if invalid
+ ********************************************************************* */
+static int
+eth_parse_xdigit(char c)
+{
+ int digit;
+
+ if ((c >= '0') && (c <= '9')) digit = c - '0';
+ else if ((c >= 'a') && (c <= 'f')) digit = c - 'a' + 10;
+ else if ((c >= 'A') && (c <= 'F')) digit = c - 'A' + 10;
+ else digit = -1;
+
+ return digit;
+}
+
+/* *********************************************************************
+ * ETH_PARSE_HWADDR(str,hwaddr)
+ *
+ * Convert a string in the form xx:xx:xx:xx:xx:xx into a 6-byte
+ * Ethernet address.
+ *
+ * Input parameters:
+ * str - string
+ * hwaddr - pointer to hardware address
+ *
+ * Return value:
+ * 0 if ok, else -1
+ ********************************************************************* */
+static int
+eth_parse_hwaddr(char *str, uint8_t *hwaddr)
+{
+ int digit1, digit2;
+ int idx = ENET_ADDR_LEN;
+
+ while (*str && (idx > 0)) {
+ digit1 = eth_parse_xdigit(*str);
+ if (digit1 < 0) return -1;
+ str++;
+ if (!*str) return -1;
+
+ if ((*str == ':') || (*str == '-')) {
+ digit2 = digit1;
+ digit1 = 0;
+ }
+ else {
+ digit2 = eth_parse_xdigit(*str);
+ if (digit2 < 0) return -1;
+ str++;
+ }
+
+ *hwaddr++ = (digit1 << 4) | digit2;
+ idx--;
+
+ if ((*str == ':') || (*str == '-'))
+ str++;
+ }
+ return 0;
+}
+
+/* *********************************************************************
+ * ETH_INCR_HWADDR(hwaddr,incr)
+ *
+ * Increment a 6-byte Ethernet hardware address, with carries
+ *
+ * Input parameters:
+ * hwaddr - pointer to hardware address
+ * incr - desired increment
+ *
+ * Return value:
+ * none
+ ********************************************************************* */
+static void
+eth_incr_hwaddr(uint8_t *hwaddr, unsigned incr)
+{
+ int idx;
+ int carry;
+
+ idx = 5;
+ carry = incr;
+ while (idx >= 0 && carry != 0) {
+ unsigned sum = hwaddr[idx] + carry;
+
+ hwaddr[idx] = sum & 0xFF;
+ carry = sum >> 8;
+ idx--;
+ }
+}
+
+
+/* *********************************************************************
+ * Declarations for CFE Device Driver Interface routines
+ ********************************************************************* */
+
+static int dp83815_ether_open(cfe_devctx_t *ctx);
+static int dp83815_ether_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int dp83815_ether_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int dp83815_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int dp83815_ether_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int dp83815_ether_close(cfe_devctx_t *ctx);
+static void dp83815_ether_poll(cfe_devctx_t *ctx, int64_t ticks);
+static void dp83815_ether_reset(void *softc);
+
+/* *********************************************************************
+ * CFE Device Driver dispatch structure
+ ********************************************************************* */
+
+const static cfe_devdisp_t dp83815_ether_dispatch = {
+ dp83815_ether_open,
+ dp83815_ether_read,
+ dp83815_ether_inpstat,
+ dp83815_ether_write,
+ dp83815_ether_ioctl,
+ dp83815_ether_close,
+ dp83815_ether_poll,
+ dp83815_ether_reset
+};
+
+/* *********************************************************************
+ * CFE Device Driver descriptor
+ ********************************************************************* */
+
+const cfe_driver_t dp83815drv = {
+ "DP83815 Ethernet",
+ "eth",
+ CFE_DEV_NETWORK,
+ &dp83815_ether_dispatch,
+ dp83815_ether_probe
+};
+
+
+static int
+dp83815_ether_attach(cfe_driver_t *drv,
+ pcitag_t tag, int index, uint8_t hwaddr[])
+{
+ dp83815_softc *sc;
+ uint32_t device;
+ uint32_t class;
+ phys_addr_t pa;
+ uint8_t promaddr[ENET_ADDR_LEN];
+ char descr[100];
+ uint32_t srr;
+
+ device = pci_conf_read(tag, R_CFGID);
+ class = pci_conf_read(tag, R_CFGRID);
+
+#if 1
+ /* Use memory space for the CSRs */
+ pci_map_mem(tag, R_CFGMA, PCI_MATCH_BITS, &pa);
+#else
+ /* Use i/o space for the CSRs */
+ pci_map_io(tag, R_CFGIOA, PCI_MATCH_BITS, &pa);
+#endif
+
+ sc = (dp83815_softc *) KMALLOC(sizeof(dp83815_softc), 0);
+
+ if (sc == NULL) {
+ xprintf("DP83815: No memory to complete probe\n");
+ return 0;
+ }
+ memset(sc, 0, sizeof(*sc));
+
+ sc->membase = (uint32_t)pa;
+ sc->irq = pci_conf_read(tag, R_CFGINT) & 0xFF;
+ sc->tag = tag;
+ sc->device = PCI_PRODUCT(device);
+ sc->revision = PCI_REVISION(class);
+ sc->devctx = NULL;
+
+#if 1
+ sc->linkspeed = ETHER_SPEED_AUTO; /* select autonegotiation */
+#else
+ sc->linkspeed = ETHER_SPEED_100FDX; /* 100 Mbps, full duplex */
+#endif
+ sc->loopback = ETHER_LOOPBACK_OFF;
+ memcpy(sc->hwaddr, hwaddr, ENET_ADDR_LEN);
+
+ srr = READCSR(sc, R_SRR);
+#if 0
+ /* The NS data sheet recommends the following for "optimal
+ performance" of CVNG parts. Tested on a sample of one CVNG
+ part on an NS "Macphyter Demo II" eval board, it seemed to
+ produce slightly less reliable initial behavior. */
+ if (G_SRR_REV(srr) == K_REV_CVNG) {
+ /* Update PHY DSP registers per data sheet. */
+ WRITECSR(sc, R_PGSEL, 0x0001);
+ (void)READCSR(sc, R_PGSEL); /* push */
+ WRITECSR(sc, R_PMDCSR, 0x189C);
+ WRITECSR(sc, R_TSTDAT, 0x0000);
+ WRITECSR(sc, R_DSPCFG, 0x5040);
+ WRITECSR(sc, R_SDCFG, 0x008C);
+ }
+#endif
+
+ dp83815_init(sc);
+
+ /* Prefer the address in EEPROM. This will be read into the
+ PMATCH register upon power up. Unfortunately, how to test for
+ completion of the auto-load (but see PTSCR_EELOAD_EN). */
+ if (dp83815_get_pm_addr(sc, promaddr) == 0) {
+ memcpy(sc->hwaddr, promaddr, ENET_ADDR_LEN);
+ }
+
+ sc->state = eth_state_uninit;
+
+ xsprintf(descr, "%s at 0x%X (%02x-%02x-%02x-%02x-%02x-%02x)",
+ drv->drv_description, sc->membase,
+ sc->hwaddr[0], sc->hwaddr[1], sc->hwaddr[2],
+ sc->hwaddr[3], sc->hwaddr[4], sc->hwaddr[5]);
+
+ cfe_attach(drv, sc, NULL, descr);
+ return 1;
+}
+
+
+/* *********************************************************************
+ * DP83815_ETHER_PROBE(drv,probe_a,probe_b,probe_ptr)
+ *
+ * Probe and install drivers for all dp83815 Ethernet controllers.
+ * For each, create a context structure and attach to the
+ * specified network device.
+ *
+ * Input parameters:
+ * drv - driver descriptor
+ * probe_a - not used
+ * probe_b - not used
+ * probe_ptr - string pointer to hardware address for the first
+ * MAC, in the form xx:xx:xx:xx:xx:xx
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void
+dp83815_ether_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ int n;
+ uint8_t hwaddr[ENET_ADDR_LEN];
+
+ if (probe_ptr)
+ eth_parse_hwaddr((char *) probe_ptr, hwaddr);
+ else {
+ /* use default address 02-00-00-10-0B-00 */
+ hwaddr[0] = 0x02; hwaddr[1] = 0x00; hwaddr[2] = 0x00;
+ hwaddr[3] = 0x10; hwaddr[4] = 0x0B; hwaddr[5] = 0x00;
+ }
+
+ n = 0;
+ for (;;) {
+ pcitag_t tag;
+
+ if (pci_find_device(K_PCI_VENDOR_NSC, K_PCI_ID_DP83815, n, &tag) != 0)
+ break;
+ dp83815_ether_attach(drv, tag, n, hwaddr);
+ n++;
+ eth_incr_hwaddr(hwaddr, 1);
+ }
+}
+
+
+/* The functions below are called via the dispatch vector for the 83815. */
+
+/* *********************************************************************
+ * DP83815_ETHER_OPEN(ctx)
+ *
+ * Open the Ethernet device. The MAC is reset, initialized, and
+ * prepared to receive and send packets.
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+dp83815_ether_open(cfe_devctx_t *ctx)
+{
+ dp83815_softc *sc = ctx->dev_softc;
+
+ if (sc->state == eth_state_on)
+ dp83815_stop(sc);
+
+ sc->devctx = ctx;
+
+ sc->inpkts = sc->outpkts = 0;
+ sc->interrupts = 0;
+ sc->rx_interrupts = sc->tx_interrupts = 0;
+
+ dp83815_start(sc);
+
+#if XPOLL
+ dp83815_isr(sc);
+#endif
+
+ return 0;
+}
+
+/* *********************************************************************
+ * DP83815_ETHER_READ(ctx,buffer)
+ *
+ * Read a packet from the Ethernet device. If no packets are
+ * available, the read will succeed but return 0 bytes.
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ * buffer - pointer to buffer descriptor.
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+dp83815_ether_read(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ dp83815_softc *sc = ctx->dev_softc;
+ eth_pkt_t *pkt;
+ int blen;
+
+#if XPOLL
+ dp83815_isr(sc);
+#endif
+
+ if (sc->state != eth_state_on) return -1;
+
+ CS_ENTER(sc);
+ pkt = (eth_pkt_t *) q_deqnext(&(sc->rxqueue));
+ CS_EXIT(sc);
+
+ if (pkt == NULL) {
+ buffer->buf_retlen = 0;
+ return 0;
+ }
+
+ blen = buffer->buf_length;
+ if (blen > pkt->length) blen = pkt->length;
+
+ blockcopy(buffer->buf_ptr, pkt->buffer, blen);
+ buffer->buf_retlen = blen;
+
+ eth_free_pkt(sc, pkt);
+ dp83815_fillrxring(sc);
+
+#if XPOLL
+ dp83815_isr(sc);
+#endif
+
+ return 0;
+}
+
+/* *********************************************************************
+ * DP83815_ETHER_INPSTAT(ctx,inpstat)
+ *
+ * Check for received packets on the Ethernet device
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ * inpstat - pointer to input status structure
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+dp83815_ether_inpstat(cfe_devctx_t *ctx, iocb_inpstat_t *inpstat)
+{
+ dp83815_softc *sc = ctx->dev_softc;
+
+#if XPOLL
+ dp83815_isr(sc);
+#endif
+
+ if (sc->state != eth_state_on) return -1;
+
+ /* We avoid an interlock here because the result is a hint and an
+ interrupt cannot turn a non-empty queue into an empty one. */
+ inpstat->inp_status = (q_isempty(&(sc->rxqueue))) ? 0 : 1;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * DP83815_ETHER_WRITE(ctx,buffer)
+ *
+ * Write a packet to the Ethernet device.
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ * buffer - pointer to buffer descriptor.
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+dp83815_ether_write(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ dp83815_softc *sc = ctx->dev_softc;
+ eth_pkt_t *pkt;
+ int blen;
+
+#if XPOLL
+ dp83815_isr(sc);
+#endif
+
+ if (sc->state != eth_state_on) return -1;
+
+ pkt = eth_alloc_pkt(sc);
+ if (!pkt) return CFE_ERR_NOMEM;
+
+ blen = buffer->buf_length;
+ if (blen > pkt->length) blen = pkt->length;
+
+ blockcopy(pkt->buffer, buffer->buf_ptr, blen);
+ pkt->length = blen;
+
+ if (dp83815_transmit(sc, pkt) != 0) {
+ eth_free_pkt(sc,pkt);
+ return CFE_ERR_IOERR;
+ }
+
+#if XPOLL
+ dp83815_isr(sc);
+#endif
+
+ return 0;
+}
+
+/* *********************************************************************
+ * DP83815_ETHER_IOCTL(ctx,buffer)
+ *
+ * Do device-specific I/O control operations for the device
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ * buffer - pointer to buffer descriptor.
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+dp83815_ether_ioctl(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ dp83815_softc *sc = ctx->dev_softc;
+ int *argp;
+ int mode;
+ int speed;
+
+ switch ((int)buffer->buf_ioctlcmd) {
+ case IOCTL_ETHER_GETHWADDR:
+ memcpy(buffer->buf_ptr, sc->hwaddr, sizeof(sc->hwaddr));
+ return 0;
+
+ case IOCTL_ETHER_SETHWADDR:
+ return -1; /* not supported */
+
+ case IOCTL_ETHER_GETSPEED:
+ argp = (int *) buffer->buf_ptr;
+ *argp = sc->linkspeed;
+ return 0;
+
+ case IOCTL_ETHER_SETSPEED:
+ dp83815_stop(sc);
+ dp83815_resetrings(sc);
+ speed = *((int *) buffer->buf_ptr);
+ dp83815_setspeed(sc, speed);
+ dp83815_start(sc);
+ sc->state = eth_state_on;
+ return 0;
+
+ case IOCTL_ETHER_GETLINK:
+ argp = (int *) buffer->buf_ptr;
+ *argp = sc->linkspeed;
+ return 0;
+
+ case IOCTL_ETHER_GETLOOPBACK:
+ *((int *) buffer) = sc->loopback;
+ return 0;
+
+ case IOCTL_ETHER_SETLOOPBACK:
+ dp83815_stop(sc);
+ dp83815_resetrings(sc);
+ mode = *((int *) buffer->buf_ptr);
+ sc->loopback = ETHER_LOOPBACK_OFF; /* default */
+ if (mode == ETHER_LOOPBACK_INT || mode == ETHER_LOOPBACK_EXT) {
+ dp83815_setloopback(sc, mode);
+ }
+ dp83815_start(sc);
+ sc->state = eth_state_on;
+ return 0;
+
+ default:
+ return -1;
+ }
+}
+
+/* *********************************************************************
+ * DP83815_ETHER_CLOSE(ctx)
+ *
+ * Close the Ethernet device.
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+dp83815_ether_close(cfe_devctx_t *ctx)
+{
+ dp83815_softc *sc = ctx->dev_softc;
+
+ sc->state = eth_state_off;
+ dp83815_stop(sc);
+
+ /* resynchronize descriptor rings */
+ dp83815_resetrings(sc);
+
+ xprintf("%s: %d sent, %d received, %d interrupts\n",
+ dp83815_devname(sc), sc->outpkts, sc->inpkts, sc->interrupts);
+ xprintf(" %d rx interrupts, %d tx interrupts\n",
+ sc->rx_interrupts, sc->tx_interrupts);
+
+ sc->devctx = NULL;
+ return 0;
+}
+
+
+/* *********************************************************************
+ * DP83815_ETHER_POLL(ctx,ticks)
+ *
+ * TBD
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ * ticks- current time in ticks
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void
+dp83815_ether_poll(cfe_devctx_t *ctx, int64_t ticks)
+{
+ dp83815_softc *sc = ctx->dev_softc;
+
+ if (sc->phy_check) {
+ sc->phy_check = 0;
+ dp83815_checkphy(sc);
+ }
+}
+
+
+/* *********************************************************************
+ * DP83815_ETHER_RESET(softc)
+ *
+ * This routine is called when CFE is restarted after a
+ * program exits. We can clean up pending I/Os here.
+ *
+ * Input parameters:
+ * softc - pointer to dp83815_softc
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void
+dp83815_ether_reset(void *softc)
+{
+ dp83815_softc *sc = (dp83815_softc *)softc;
+
+ /* Turn off the Ethernet interface. */
+
+ /* RESET_ADAPTER(sc); */
+
+ sc->state = eth_state_uninit;
+}
diff --git a/cfe/cfe/dev/dev_ds17887clock.c b/cfe/cfe/dev/dev_ds17887clock.c
new file mode 100644
index 0000000..2ee82a3
--- /dev/null
+++ b/cfe/cfe/dev/dev_ds17887clock.c
@@ -0,0 +1,422 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * DS17887-3 RTC driver File: dev_sb1250_ds17887clock.c
+ *
+ * This module contains a CFE driver for a DS17887-3 generic bus
+ * real-time-clock.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+
+#include "lib_physio.h"
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+/*
+ * Register bits
+ */
+
+#define DS17887REGA_UIP 0x80 /* Update-in-progress */
+#define DS17887REGA_DV2 0x40 /* Countdown chain */
+#define DS17887REGA_DV1 0x20 /* Oscillator enable */
+#define DS17887REGA_DV0 0x10 /* Bank Select */
+#define DS17887REGA_RS3 0x08 /* Rate-selection bits */
+#define DS17887REGA_RS2 0x04
+#define DS17887REGA_RS1 0x02
+#define DS17887REGA_RS0 0x01
+
+#define DS17887REGB_SET 0x80 /* Set bit */
+#define DS17887REGB_PIE 0x40 /* Periodic Interrupt Enable */
+#define DS17887REGB_AIE 0x20 /* Alarm Interrupt Enable */
+#define DS17887REGB_UIE 0x10 /* Update-ended Interrupt Enable */
+#define DS17887REGB_SQWE 0x08 /* Square-wave Enable */
+#define DS17887REGB_DM 0x04 /* Data Mode (binary) */
+#define DS17887REGB_24 0x02 /* 24-hour mode control bit */
+#define DS17887REGB_DSE 0x01 /* Daylight Savings Enable */
+
+#define DS17887REGC_IRQF 0x80 /* Interrupt request flag */
+#define DS17887REGC_PF 0x40 /* Periodic interrupt flag */
+#define DS17887REGC_AF 0x20 /* Alarm interrupt flag */
+#define DS17887REGC_UF 0x10 /* Update ended interrupt flag */
+
+#define DS17887REGD_VRT 0x80 /* Valid RAM and time */
+
+/*
+ * Register numbers
+ */
+
+#define DS17887REG_SC 0x00 /* seconds */
+#define DS17887REG_SCA 0x01 /* seconds alarm */
+#define DS17887REG_MN 0x02 /* minutes */
+#define DS17887REG_MNA 0x03 /* minutes alarm */
+#define DS17887REG_HR 0x04 /* hours */
+#define DS17887REG_HRA 0x05 /* hours alarm */
+#define DS17887REG_DW 0x06 /* day of week */
+#define DS17887REG_DM 0x07 /* day of month */
+#define DS17887REG_MO 0x08 /* month */
+#define DS17887REG_YR 0x09 /* year */
+#define DS17887REG_A 0x0A /* register A */
+#define DS17887REG_B 0x0B /* register B */
+#define DS17887REG_C 0x0C /* register C */
+#define DS17887REG_D 0x0D /* register D */
+
+#define DS17887REG_CE 0x48 /* century (bank 1 only) */
+
+#define BCD(x) (((x) % 10) + (((x) / 10) << 4))
+#define SET_TIME 0x00
+#define SET_DATE 0x01
+
+#define WRITECSR(p,v) phys_write8((p),(v))
+#define READCSR(p) phys_read8((p))
+
+/* *********************************************************************
+ * Forward declarations
+ ********************************************************************* */
+
+static void ds17887_clock_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+static int ds17887_clock_open(cfe_devctx_t *ctx);
+static int ds17887_clock_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int ds17887_clock_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int ds17887_clock_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int ds17887_clock_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int ds17887_clock_close(cfe_devctx_t *ctx);
+
+
+/* *********************************************************************
+ * Device dispatch
+ ********************************************************************* */
+
+const static cfe_devdisp_t ds17887_clock_dispatch = {
+ ds17887_clock_open,
+ ds17887_clock_read,
+ ds17887_clock_inpstat,
+ ds17887_clock_write,
+ ds17887_clock_ioctl,
+ ds17887_clock_close,
+ NULL,
+ NULL
+};
+
+const cfe_driver_t ds17887_clock = {
+ "DS17887 RTC",
+ "clock",
+ CFE_DEV_CLOCK,
+ &ds17887_clock_dispatch,
+ ds17887_clock_probe
+};
+
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+typedef struct ds17887_clock_s {
+ physaddr_t clock_base;
+} ds17887_clock_t;
+
+/* *********************************************************************
+ * ds17887_clock_probe(drv,a,b,ptr)
+ *
+ * Probe routine for this driver. This routine creates the
+ * local device context and attaches it to the driver list
+ * within CFE.
+ *
+ * Input parameters:
+ * drv - driver handle
+ * a,b - probe hints (longs)
+ * ptr - probe hint (pointer)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void ds17887_clock_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ ds17887_clock_t *softc;
+ char descr[80];
+
+ softc = (ds17887_clock_t *) KMALLOC(sizeof(ds17887_clock_t),0);
+
+ /*
+ * Probe_a is the clock base address
+ * Probe_b is unused.
+ * Probe_ptr is unused.
+ */
+
+ softc->clock_base = probe_a;
+
+ xsprintf(descr,"%s at 0x%X",
+ drv->drv_description,(uint32_t)probe_a);
+ cfe_attach(drv,softc,NULL,descr);
+
+}
+
+/* *********************************************************************
+ * ds17887_clock_open(ctx)
+ *
+ * Open this device. For the DS17887, we do a quick test
+ * read to be sure the device is out there.
+ *
+ * Input parameters:
+ * ctx - device context (can obtain our softc here)
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int ds17887_clock_open(cfe_devctx_t *ctx)
+{
+ ds17887_clock_t *softc = ctx->dev_softc;
+ uint8_t byte;
+ physaddr_t clockbase;
+
+ clockbase = softc->clock_base;
+
+ /* Make sure battery is still good and RTC valid */
+ if ( !(READCSR(clockbase+DS17887REG_D) & DS17887REGD_VRT) ) {
+ printf("Warning: Battery has failed. Clock setting is not accurate.\n");
+ }
+
+ /* Switch to bank 1. Mainly for century byte */
+ byte = (uint8_t) (READCSR(clockbase+DS17887REG_A) & 0xFF);
+ WRITECSR(clockbase+DS17887REG_A,DS17887REGA_DV0 | DS17887REGA_DV1 | byte);
+
+ /* Set data mode to BCD, 24-hour mode, and enable daylight savings */
+ byte = (uint8_t) (READCSR(clockbase+DS17887REG_B) & 0xFF);
+ byte &= (~DS17887REGB_DM & ~DS17887REGB_AIE);
+ WRITECSR(clockbase+DS17887REG_B, DS17887REGB_24 | DS17887REGB_DSE | byte );
+
+ return 0;
+}
+
+/* *********************************************************************
+ * ds17887_clock_read(ctx,buffer)
+ *
+ * Read time/date from the RTC. Read a total of 8 bytes in this format:
+ * hour-minute-second-month-day-year1-year2
+ *
+ * Input parameters:
+ * ctx - device context (can obtain our softc here)
+ * buffer - buffer descriptor (target buffer, length, offset)
+ *
+ * Return value:
+ * number of bytes read
+ * -1 if an error occured
+ ********************************************************************* */
+
+static int ds17887_clock_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+
+ ds17887_clock_t *softc = ctx->dev_softc;
+ unsigned char *bptr;
+ physaddr_t clockbase;
+
+ clockbase = softc->clock_base;
+
+ bptr = buffer->buf_ptr;
+
+ *bptr++ = READCSR(clockbase+DS17887REG_HR);
+ *bptr++ = READCSR(clockbase+DS17887REG_MN);
+ *bptr++ = READCSR(clockbase+DS17887REG_SC);
+ *bptr++ = READCSR(clockbase+DS17887REG_MO);
+ *bptr++ = READCSR(clockbase+DS17887REG_DM);
+ *bptr++ = READCSR(clockbase+DS17887REG_YR);
+ *bptr++ = READCSR(clockbase+DS17887REG_CE);
+
+ buffer->buf_retlen = 8;
+ return 0;
+}
+
+/* *********************************************************************
+ * ds17887_clock_write(ctx,buffer)
+ *
+ * Write time/date to the RTC. Write in this format:
+ * hour-minute-second-month-day-year1-year2-(time/date flag)
+ *
+ * Input parameters:
+ * ctx - device context (can obtain our softc here)
+ * buffer - buffer descriptor (target buffer, length, offset)
+ *
+ * Return value:
+ * number of bytes written
+ * -1 if an error occured
+ ********************************************************************* */
+
+static int ds17887_clock_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ ds17887_clock_t *softc = ctx->dev_softc;
+ uint8_t byte;
+ unsigned char *bptr;
+ uint8_t hr,min,sec;
+ uint8_t mo,day,yr,y2k;
+ uint8_t timeDateFlag;
+ physaddr_t clockbase;
+
+ clockbase = softc->clock_base;
+
+ bptr = buffer->buf_ptr;
+
+ /* Set SET bit */
+ byte = (uint8_t) (READCSR(clockbase+DS17887REG_B) & 0xFF);
+ WRITECSR(clockbase+DS17887REG_B,DS17887REGB_SET | byte);
+
+ timeDateFlag = *(bptr + 7);
+
+ /* write time or date */
+ if(timeDateFlag == SET_TIME) {
+
+ hr = (uint8_t) *bptr;
+ WRITECSR(clockbase+DS17887REG_HR,BCD(hr));
+
+ min = (uint8_t) *(bptr+1);
+ WRITECSR(clockbase+DS17887REG_MN,BCD(min));
+
+ sec = (uint8_t) *(bptr+2);
+ WRITECSR(clockbase+DS17887REG_SC,BCD(sec));
+
+ buffer->buf_retlen = 3;
+ }
+ else if(timeDateFlag == SET_DATE) {
+
+ mo = (uint8_t) *(bptr+3);
+ WRITECSR(clockbase+DS17887REG_MO,BCD(mo));
+
+ day = (uint8_t) *(bptr+4);
+ WRITECSR(clockbase+DS17887REG_DM,BCD(day));
+
+ yr = (uint8_t) *(bptr+5);
+ WRITECSR(clockbase+DS17887REG_YR,BCD(yr));
+
+ y2k = (uint8_t) *(bptr+6);
+ WRITECSR(clockbase+DS17887REG_CE,y2k);
+
+ buffer->buf_retlen = 4;
+ }
+ else {
+ return -1;
+ }
+
+ /* clear SET bit */
+ byte = (uint8_t) (READCSR(clockbase+DS17887REG_B) & 0xFF);
+ WRITECSR(clockbase+DS17887REG_B,~DS17887REGB_SET & byte);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * ds17887_clock_inpstat(ctx,inpstat)
+ *
+ * Test input (read) status for the device
+ *
+ * Input parameters:
+ * ctx - device context (can obtain our softc here)
+ * inpstat - input status descriptor to receive value
+ *
+ * Return value:
+ * 0 if ok
+ * -1 if an error occured
+ ********************************************************************* */
+
+static int ds17887_clock_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
+{
+ inpstat->inp_status = 1;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * ds17887_clock_ioctl(ctx,buffer)
+ *
+ * Perform miscellaneous I/O control operations on the device.
+ *
+ * Input parameters:
+ * ctx - device context (can obtain our softc here)
+ * buffer - buffer descriptor (target buffer, length, offset)
+ *
+ * Return value:
+ * number of bytes read
+ * -1 if an error occured
+ ********************************************************************* */
+
+static int ds17887_clock_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ return 0;
+}
+
+/* *********************************************************************
+ * ds17887_clock_close(ctx,buffer)
+ *
+ * Close the device.
+ *
+ * Input parameters:
+ * ctx - device context (can obtain our softc here)
+ *
+ * Return value:
+ * 0 if ok
+ * -1 if an error occured
+ ********************************************************************* */
+
+static int ds17887_clock_close(cfe_devctx_t *ctx)
+{
+ return 0;
+}
+
+
+
+
+
+
+
+
diff --git a/cfe/cfe/dev/dev_flash.c b/cfe/cfe/dev/dev_flash.c
new file mode 100644
index 0000000..98ad3e7
--- /dev/null
+++ b/cfe/cfe/dev/dev_flash.c
@@ -0,0 +1,1367 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Flash device driver File: dev_flash.c
+ *
+ * This driver supports various types of flash
+ * parts. You can also put the environment storage in
+ * the flash - the top sector is reserved for that purpose.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "addrspace.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+#include "cfe_error.h"
+
+#include "dev_flash.h"
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define FLASHCMD(sc,x,y) *((volatile unsigned char *)(sc->flashdrv_cmdaddr+ \
+ ((x)<<(sc)->flashdrv_widemode))) = (y)
+#define FLASHSTATUS(sc,x) *((volatile unsigned char *)(sc->flashdrv_cmdaddr+ \
+ ((x)<<(sc)->flashdrv_widemode)))
+
+#define WRITEFLASH_K1(sc,x,y) *((volatile unsigned char *)(sc->flashdrv_cmdaddr+(x))) = (y)
+#define READFLASH_K1(sc,x) *((volatile unsigned char *)(sc->flashdrv_cmdaddr+(x)))
+
+#define WRITEFLASH_K1W(sc,x,y) *((volatile unsigned short *)(sc->flashdrv_cmdaddr+(x))) = (y)
+#define READFLASH_K1W(sc,x) *((volatile unsigned short *)(sc->flashdrv_cmdaddr+(x)))
+
+
+#define GETCFIBYTE(softc,offset) READFLASH_K1(softc,((offset) << (softc->flashdrv_widemode)))
+
+/* *********************************************************************
+ * Forward declarations
+ ********************************************************************* */
+
+
+static void flashdrv_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+
+static int flashdrv_open(cfe_devctx_t *ctx);
+static int flashdrv_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int flashdrv_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int flashdrv_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int flashdrv_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int flashdrv_close(cfe_devctx_t *ctx);
+
+/* *********************************************************************
+ * Device dispatch
+ ********************************************************************* */
+
+const static cfe_devdisp_t flashdrv_dispatch = {
+ flashdrv_open,
+ flashdrv_read,
+ flashdrv_inpstat,
+ flashdrv_write,
+ flashdrv_ioctl,
+ flashdrv_close,
+ NULL,
+ NULL
+};
+
+const cfe_driver_t flashdrv = {
+ "CFI flash",
+ "flash",
+ CFE_DEV_FLASH,
+ &flashdrv_dispatch,
+ flashdrv_probe
+};
+
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef struct flash_cfidata_s {
+ unsigned int cfidata_cmdset; /* ID of primary command set */
+ unsigned int cfidata_devif; /* device interface byte */
+ unsigned int cfidata_size; /* probed device size */
+} flash_cfidata_t;
+
+typedef struct flashops_s flashops_t;
+
+typedef struct flashdrv_s {
+ flash_probe_t flashdrv_probe; /* data from probe */
+ int flashdrv_devsize; /* size reported by driver */
+ unsigned char *flashdrv_cmdaddr; /* virtual address (K1) */
+ int flashdrv_widemode; /* 1=wide flash in byte mode, 0=narrow flash */
+ int flashdrv_initialized; /* true if we've probed already */
+ flash_info_t flashdrv_info;
+ int flashdrv_nvram_ok; /* true if we can use as NVRAM */
+ int flashdrv_unlocked; /* true if we can r/w past devsize */
+ nvram_info_t flashdrv_nvraminfo;
+ flashops_t *flashdrv_ops;
+ flash_cfidata_t flashdrv_cfidata;
+} flashdrv_t;
+
+struct flashops_s {
+ int (*erasesector)(flashdrv_t *f,int offset);
+ int (*writeblk)(flashdrv_t *f,int offset,void *buf,int len);
+};
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define FLASHOP_ERASE_SECTOR(softc,sect) (*((softc)->flashdrv_ops->erasesector))((softc),(sect))
+#define FLASHOP_WRITE_BLOCK(softc,off,buf,len) (*((softc)->flashdrv_ops->writeblk))((softc),(off),(buf),(len))
+
+/* *********************************************************************
+ * forward declarations
+ ********************************************************************* */
+
+
+static int flash_sector_query(flashdrv_t *softc,flash_sector_t *sector);
+
+static int amd_flash_write_block(flashdrv_t *softc,int offset,void *buf,int len);
+static int amd_flash_erase_sector(flashdrv_t *softc,int offset);
+
+static int intel_flash_write_block(flashdrv_t *softc,int offset,void *buf,int len);
+static int intel_flash_erase_sector(flashdrv_t *softc,int offset);
+
+static flashops_t amd_flashops = {
+ amd_flash_erase_sector,
+ amd_flash_write_block,
+};
+
+static flashops_t intel_flashops = {
+ intel_flash_erase_sector,
+ intel_flash_write_block,
+};
+
+#define FLASHOPS_DEFAULT amd_flashops
+
+
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+extern void *flash_write_all_ptr;
+extern int flash_write_all_len;
+
+extern void _cfe_flushcache(int);
+
+
+#if 0
+/* *********************************************************************
+ * jedec_flash_maufacturer(softc)
+ *
+ * Return the manufacturer ID for this flash part.
+ *
+ * Input parameters:
+ * softc - flash context
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static unsigned int jedec_flash_manufacturer(flashdrv_t *softc)
+{
+ unsigned int res;
+
+ /* Do an "unlock write" sequence */
+ FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
+ FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
+ FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL);
+
+ res = FLASHSTATUS(softc,FLASH_JEDEC_OFFSET_MFR) & 0xFF;
+
+ FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_RESET);
+
+ return res;
+}
+
+/* *********************************************************************
+ * jedec_flash_type(softc)
+ *
+ * Return the manufacturer's type for the flash
+ *
+ * Input parameters:
+ * softc - flash context
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static unsigned int jedec_flash_type(flashdrv_t *softc)
+{
+ unsigned int res;
+
+ /* Do an "unlock write" sequence */
+ FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
+ FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
+ FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_AUTOSEL);
+
+ res = FLASHSTATUS(softc,FLASH_JEDEC_OFFSET_DEV) & 0xFF;
+
+ FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_RESET);
+
+ return res;
+}
+
+#endif
+
+/* *********************************************************************
+ * amd_flash_write_byte(softc,offset,val)
+ *
+ * Write a single byte to the flash. The sector that the flash
+ * byte is in should have been previously erased, or else this
+ * routine may hang.
+ *
+ * Input parameters:
+ * softc - flash context
+ * offset - distance in bytes into the flash
+ * val - byte to write
+ *
+ * Return value:
+ * 0 if ok
+ * else if flash could not be written
+ ********************************************************************* */
+static inline int amd_flash_write_byte(flashdrv_t *softc,int offset, unsigned char val)
+{
+ unsigned int value;
+
+ /* Do an "unlock write" sequence */
+ FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1);
+ FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
+
+ /* Send a program command */
+ FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_PROGRAM);
+
+ /* Write a byte */
+ WRITEFLASH_K1(softc,offset,val);
+
+ for (;;) {
+ value = READFLASH_K1(softc,offset) & 0xFF;
+
+ if ((value & 0x80) == (val & 0x80)) {
+ return 0;
+ }
+ if ((value & 0x20) != 0x20) {
+ continue;
+ }
+
+ if ((READFLASH_K1(softc,offset) & 0x80) == (val & 0x80)) {
+ return 0;
+ }
+ else {
+ return -1;
+ }
+ }
+}
+
+
+/* *********************************************************************
+ * amd_flash_write_block(softc,offset,val)
+ *
+ * Write a single byte to the flash. The sector that the flash
+ * byte is in should have been previously erased, or else this
+ * routine may hang.
+ *
+ * Input parameters:
+ * softc - flash context
+ * offset - distance in bytes into the flash
+ * buf - buffer of bytes to write
+ * len - number of bytes to write
+ *
+ * Return value:
+ * number of bytes written
+ ********************************************************************* */
+static int amd_flash_write_block(flashdrv_t *softc,int offset,void *buf,int len)
+{
+ unsigned char *ptr;
+
+ ptr = buf;
+
+ while (len) {
+ if (amd_flash_write_byte(softc,offset,*ptr) < 0) break;
+ len--;
+ ptr++;
+ offset++;
+
+ }
+
+ return (ptr - (unsigned char *)buf);
+}
+
+
+/* *********************************************************************
+ * amd_flash_erase_sector(softc,offset)
+ *
+ * Erase a single sector in the flash device
+ *
+ * Input parameters:
+ * softc - device context
+ * offset - offset in flash of sector to erase
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+static int amd_flash_erase_sector(flashdrv_t *softc,int offset)
+{
+ /* Do an "unlock write" sequence */
+ FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1); /* cycles 1-2 */
+ FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
+
+ /* send the erase command */
+ FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_ERASE_3); /* cycle 3 */
+
+ /* Do an "unlock write" sequence */
+ FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_1,AMD_FLASH_MAGIC_1); /* cycles 4-5 */
+ FLASHCMD(softc,AMD_FLASH_MAGIC_ADDR_2,AMD_FLASH_MAGIC_2);
+
+ /*
+ * Send the "erase sector" qualifier - don't use FLASHCMD
+ * because it changes the offset.
+ */
+ WRITEFLASH_K1(softc,offset,AMD_FLASH_ERASE_SEC_6);
+
+ while ((READFLASH_K1(softc,offset) & 0x80) != 0x80) {
+ /* NULL LOOP */
+ }
+
+ return 0;
+}
+
+
+
+/* *********************************************************************
+ * intel_flash_write_byte(softc,offset,val)
+ *
+ * Write a single byte to the flash. The sector that the flash
+ * byte is in should have been previously erased, or else this
+ * routine may hang.
+ *
+ * Input parameters:
+ * softc - flash context
+ * offset - distance in bytes into the flash
+ * val - byte to write
+ *
+ * Return value:
+ * 0 if ok
+ * else if flash could not be written
+ ********************************************************************* */
+static inline int intel_flash_write_byte(flashdrv_t *softc,
+ int offset, unsigned char val)
+{
+ unsigned int value;
+
+ /* Send a program command */
+ WRITEFLASH_K1(softc,offset,INTEL_FLASH_PROGRAM);
+
+ /* Write a byte */
+ WRITEFLASH_K1(softc,offset,val);
+
+
+ while ((READFLASH_K1(softc,offset) & 0x80) != 0x80) {
+ /* NULL LOOP */
+ }
+
+ value = READFLASH_K1(softc,offset) & 0xFF;
+
+ if (value & (0x01|0x08|0x10)) return -1;
+ return 0;
+}
+
+/* *********************************************************************
+ * intel_flash_write_word(softc,offset,val)
+ *
+ * Write a single word to the flash. The sector that the flash
+ * byte is in should have been previously erased, or else this
+ * routine may hang.
+ *
+ * Input parameters:
+ * softc - flash context
+ * offset - distance in bytes into the flash
+ * val - word to write
+ *
+ * Return value:
+ * 0 if ok
+ * else if flash could not be written
+ ********************************************************************* */
+static inline int intel_flash_write_word(flashdrv_t *softc,
+ int offset, unsigned short val)
+{
+ unsigned int value;
+
+
+ /* Send a program command */
+ WRITEFLASH_K1W(softc,offset,INTEL_FLASH_PROGRAM);
+
+ /* Write a byte */
+ WRITEFLASH_K1W(softc,offset,val);
+
+
+ while ((READFLASH_K1W(softc,offset) & 0x80) != 0x80) {
+ /* NULL LOOP */
+ }
+
+ value = READFLASH_K1W(softc,offset) & 0xFF;
+
+ if (value & (0x01|0x08|0x10)) return -1;
+ return 0;
+}
+
+/* *********************************************************************
+ * intel_flash_write_block(softc,offset,val)
+ *
+ * Write a single byte to the flash. The sector that the flash
+ * byte is in should have been previously erased, or else this
+ * routine may hang.
+ *
+ * Input parameters:
+ * softc - flash context
+ * offset - distance in bytes into the flash
+ * buf - buffer of bytes to write
+ * len - number of bytes to write
+ *
+ * Return value:
+ * number of bytes written
+ ********************************************************************* */
+static int intel_flash_write_block(flashdrv_t *softc,int offset,void *buf,int len)
+{
+ unsigned char *ptr;
+ unsigned short *ptrw;
+
+ if (softc->flashdrv_probe.flash_flags & FLASH_FLG_16BIT) {
+ ptrw = buf;
+ offset &= ~1; /* offset must be even */
+ while (len > 0) {
+ if (intel_flash_write_word(softc,offset,*ptrw) < 0) break;
+ len-=2;
+ ptrw++;
+ offset+=2;
+ }
+ WRITEFLASH_K1(softc,offset,INTEL_FLASH_READ_MODE);
+ return ((unsigned char *) ptrw - (unsigned char *)buf);
+ }
+ else {
+ ptr = buf;
+ while (len) {
+ if (intel_flash_write_byte(softc,offset,*ptr) < 0) break;
+ len--;
+ ptr++;
+ offset++;
+ }
+ WRITEFLASH_K1(softc,offset,INTEL_FLASH_READ_MODE);
+ return (ptr - (unsigned char *)buf);
+ }
+
+}
+
+
+/* *********************************************************************
+ * intel_flash_erase_sector(softc,offset)
+ *
+ * Erase a single sector on the flash device
+ *
+ * Input parameters:
+ * softc - device context
+ * offset - offset in flash of sector to erase
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+static int intel_flash_erase_sector(flashdrv_t *softc,int offset)
+{
+ WRITEFLASH_K1(softc,offset,INTEL_FLASH_ERASE_BLOCK);
+ WRITEFLASH_K1(softc,offset,INTEL_FLASH_ERASE_CONFIRM);
+
+ while ((READFLASH_K1(softc,offset) & 0x80) != 0x80) {
+ /* NULL LOOP */
+ }
+ WRITEFLASH_K1(softc,offset,INTEL_FLASH_READ_MODE);
+
+ return 0;
+}
+
+
+
+
+
+/* *********************************************************************
+ * FLASH_ERASE_RANGE(softc,range)
+ *
+ * Erase a range of sectors
+ *
+ * Input parameters:
+ * softc - our flash
+ * range - range structure
+ *
+ * Return value:
+ * 0 if ok
+ * else error
+ ********************************************************************* */
+
+static int flash_erase_range(flashdrv_t *softc,flash_range_t *range)
+{
+ flash_sector_t sector;
+ int res;
+
+ if (softc->flashdrv_info.flash_type != FLASH_TYPE_FLASH) {
+ return CFE_ERR_UNSUPPORTED;
+ }
+
+
+ if (range->range_base+range->range_length > softc->flashdrv_devsize) {
+ return CFE_ERR_INV_PARAM;
+ }
+
+ res = 0;
+
+ sector.flash_sector_idx = 0;
+
+ for (;;) {
+ res = flash_sector_query(softc,&sector);
+ if (res != 0) break;
+ if (sector.flash_sector_status == FLASH_SECTOR_INVALID) {
+ break;
+ }
+
+ if ((sector.flash_sector_offset >= range->range_base) &&
+ (sector.flash_sector_offset <
+ (range->range_base+range->range_length-1))) {
+
+ if (softc->flashdrv_nvram_ok &&
+ (sector.flash_sector_offset >= softc->flashdrv_nvraminfo.nvram_offset)) {
+ break;
+ }
+ res = FLASHOP_ERASE_SECTOR(softc,sector.flash_sector_offset);
+ if (res != 0) break;
+ }
+ sector.flash_sector_idx++;
+ }
+
+ return res;
+
+}
+
+/* *********************************************************************
+ * FLASH_ERASE_ALL(softc)
+ *
+ * Erase the entire flash device, except the NVRAM area,
+ * sector-by-sector.
+ *
+ * Input parameters:
+ * softc - our flash
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int flash_erase_all(flashdrv_t *softc)
+{
+ flash_range_t range;
+
+ range.range_base = 0;
+ range.range_length = softc->flashdrv_devsize;
+
+ return flash_erase_range(softc,&range);
+}
+
+/* *********************************************************************
+ * FLASH_CFI_GETSECTORS(softc)
+ *
+ * Query the CFI information and store the sector info in our
+ * private probe structure.
+ *
+ * Input parameters:
+ * softc - our flash info
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int flash_cfi_getsectors(flashdrv_t *softc)
+{
+ int idx;
+ int regcnt;
+ int nblks;
+ int blksiz;
+
+ regcnt = GETCFIBYTE(softc,FLASH_CFI_REGION_COUNT);
+
+ softc->flashdrv_probe.flash_nsectors = regcnt;
+
+ for (idx = 0; idx < regcnt; idx++) {
+ nblks = ((int)GETCFIBYTE(softc,FLASH_CFI_REGION_TABLE+0+idx*4) +
+ (int)(GETCFIBYTE(softc,FLASH_CFI_REGION_TABLE+1+idx*4)<<8)) + 1;
+ blksiz = ((int)GETCFIBYTE(softc,FLASH_CFI_REGION_TABLE+2+idx*4) +
+ (int)(GETCFIBYTE(softc,FLASH_CFI_REGION_TABLE+3+idx*4)<<8)) * 256;
+ softc->flashdrv_probe.flash_sectors[idx] =
+ FLASH_SECTOR_RANGE(nblks,blksiz);
+ }
+
+
+ return 0;
+}
+
+/* *********************************************************************
+ * FLASH_SECTOR_QUERY(softc,sector)
+ *
+ * Query the sector information about a particular sector. You can
+ * call this iteratively to find out about all of the sectors.
+ *
+ * Input parameters:
+ * softc - our flash info
+ * sector - structure to receive sector information
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int flash_sector_query(flashdrv_t *softc,flash_sector_t *sector)
+{
+ int idx;
+ int nblks;
+ int blksiz;
+ unsigned int offset;
+ int curblk;
+
+ if (softc->flashdrv_info.flash_type != FLASH_TYPE_FLASH) {
+ return CFE_ERR_UNSUPPORTED;
+ }
+
+ if (softc->flashdrv_probe.flash_nsectors == 0) {
+ return CFE_ERR_UNSUPPORTED;
+ }
+
+ offset = 0;
+ curblk = 0;
+ for (idx = 0; idx < softc->flashdrv_probe.flash_nsectors; idx++) {
+ nblks = FLASH_SECTOR_NBLKS(softc->flashdrv_probe.flash_sectors[idx]);
+ blksiz = FLASH_SECTOR_SIZE(softc->flashdrv_probe.flash_sectors[idx]);
+ if (sector->flash_sector_idx < curblk+nblks) {
+ sector->flash_sector_status = FLASH_SECTOR_OK;
+ sector->flash_sector_offset =
+ offset + (sector->flash_sector_idx-curblk)*blksiz;
+ sector->flash_sector_size = blksiz;
+ break;
+ }
+
+ offset += (nblks)*blksiz;
+ curblk += nblks;
+ }
+
+
+ if (idx == softc->flashdrv_probe.flash_nsectors) {
+ sector->flash_sector_status = FLASH_SECTOR_INVALID;
+ }
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * FLASH_SET_CMDSET(softc,cmdset)
+ *
+ * Set the command-set that we'll honor for this flash.
+ *
+ * Input parameters:
+ * softc - our flash
+ * cmdset - FLASH_CFI_CMDSET_xxx
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void flash_set_cmdset(flashdrv_t *softc,int cmdset)
+{
+ switch (cmdset) {
+ case FLASH_CFI_CMDSET_INTEL_ECS:
+ case FLASH_CFI_CMDSET_INTEL_STD:
+ softc->flashdrv_ops = &intel_flashops;
+ /* XXX: Intel flashes don't have the "a-1" line. Yay. */
+ softc->flashdrv_widemode = 0;
+ break;
+ case FLASH_CFI_CMDSET_AMD_STD:
+ case FLASH_CFI_CMDSET_AMD_ECS:
+ softc->flashdrv_ops = &amd_flashops;
+ break;
+ default:
+ /* we don't understand the command set - treat it like ROM */
+ softc->flashdrv_info.flash_type = FLASH_TYPE_ROM;
+ }
+}
+
+
+/* *********************************************************************
+ * FLASH_CFI_PROBE(softc)
+ *
+ * Try to do a CFI query on this device. If we find the m
+ * magic signature, extract some useful information from the
+ * query structure.
+ *
+ * Input parameters:
+ * softc - out flash
+ *
+ * Return value:
+ * 0 if successful, <0 if error
+ ********************************************************************* */
+static int flash_cfi_probe(flashdrv_t *softc)
+{
+ FLASHCMD(softc,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_MODE);
+
+ if (!((GETCFIBYTE(softc,FLASH_CFI_SIGNATURE+0) == 'Q') &&
+ (GETCFIBYTE(softc,FLASH_CFI_SIGNATURE+1) == 'R') &&
+ (GETCFIBYTE(softc,FLASH_CFI_SIGNATURE+2) == 'Y'))) {
+
+ FLASHCMD(softc,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_EXIT);
+ return CFE_ERR_UNSUPPORTED;
+ }
+
+ /*
+ * Gather info from flash
+ */
+
+ softc->flashdrv_cfidata.cfidata_cmdset =
+ ((unsigned int) (GETCFIBYTE(softc,FLASH_CFI_COMMAND_SET))) +
+ (((unsigned int) (GETCFIBYTE(softc,FLASH_CFI_COMMAND_SET+1))) << 8);
+
+ softc->flashdrv_cfidata.cfidata_devif =
+ ((unsigned int) (GETCFIBYTE(softc,FLASH_CFI_DEVICE_INTERFACE))) +
+ (((unsigned int) (GETCFIBYTE(softc,FLASH_CFI_DEVICE_INTERFACE+1))) << 8);
+
+ softc->flashdrv_cfidata.cfidata_size =
+ 1 << ((unsigned int) (GETCFIBYTE(softc,FLASH_CFI_DEVICE_SIZE)));
+
+ flash_cfi_getsectors(softc);
+
+ /*
+ * Don't need to be in query mode anymore.
+ */
+
+ FLASHCMD(softc,FLASH_CFI_QUERY_ADDR,FLASH_CFI_QUERY_EXIT);
+
+ softc->flashdrv_info.flash_type = FLASH_TYPE_FLASH;
+
+ flash_set_cmdset(softc,softc->flashdrv_cfidata.cfidata_cmdset);
+
+ return 0;
+
+}
+
+/* *********************************************************************
+ * FLASH_GETWIDTH(softc,info)
+ *
+ * Try to determine the width of the flash. This is needed for
+ * management purposes, since some 16-bit flash parts in 8-bit mode
+ * have an "A-1" (address line -1) wire to select bytes within
+ * a 16-bit word. When this is present, the flash commands
+ * will have different offsets.
+ *
+ * Input parameters:
+ * softc - our flash
+ * info - flash info structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void flash_getwidth(flashdrv_t *softc,flash_info_t *info)
+{
+ softc->flashdrv_widemode = 0; /* first try narrow */
+
+ if (flash_cfi_probe(softc) == 0) {
+ return;
+ }
+
+ softc->flashdrv_widemode = 1; /* then wide */
+
+ if (flash_cfi_probe(softc) == 0) {
+ return;
+ }
+
+ /* Just return, assume not wide if no CFI interface */
+ softc->flashdrv_widemode = 0;
+
+ softc->flashdrv_info.flash_type = FLASH_TYPE_ROM; /* no CFI: treat as ROM */
+}
+
+/* *********************************************************************
+ * flash_getinfo(softc)
+ *
+ * Try to determine if the specified region is flash, ROM, SRAM,
+ * or something else.
+ *
+ * Input parameters:
+ * softc - our context
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void flash_getinfo(flashdrv_t *softc)
+{
+ uint8_t save0,save1;
+ volatile uint8_t *ptr;
+ flash_info_t *info = &(softc->flashdrv_info);
+
+ /*
+ * Set up some defaults based on the probe data
+ */
+
+ softc->flashdrv_widemode = 0;
+ info->flash_base = softc->flashdrv_probe.flash_phys;
+ info->flash_size = softc->flashdrv_probe.flash_size;
+ softc->flashdrv_devsize = softc->flashdrv_probe.flash_size;
+ info->flash_type = FLASH_TYPE_UNKNOWN;
+ info->flash_flags = 0;
+
+ /*
+ * If we've been told not to try probing, just assume
+ * we're a flash part.
+ */
+
+ if (softc->flashdrv_probe.flash_flags & FLASH_FLG_MANUAL) {
+ info->flash_type = FLASH_TYPE_FLASH;
+ if (softc->flashdrv_probe.flash_flags & FLASH_FLG_WIDE) {
+ softc->flashdrv_widemode = TRUE;
+ }
+ if (softc->flashdrv_probe.flash_cmdset) {
+ flash_set_cmdset(softc,softc->flashdrv_probe.flash_cmdset);
+ }
+ return;
+ }
+
+ /*
+ * Attempt to read/write byte zero. If it is changable,
+ * this is SRAM (or maybe a ROM emulator with the write line hooked up)
+ */
+
+ ptr = (volatile uint8_t *) UNCADDR(softc->flashdrv_probe.flash_phys);
+ save0 = *ptr; /* save old value */
+ save1 = *(ptr+1); /* save old value */
+ *(ptr) = 0x55;
+ if ((*ptr) == 0x55) {
+ *(ptr) = 0xAA;
+ if ((*ptr) == 0xAA) {
+ info->flash_type = FLASH_TYPE_SRAM;
+ }
+ }
+
+ if (*ptr == save0) info->flash_type = FLASH_TYPE_ROM;
+ else (*ptr) = save0; /* restore old value */
+
+ /*
+ * If we thought it was ROM, try doing a CFI query
+ * to see if it was flash. This check is kind of kludgey
+ * but should work.
+ */
+
+ if (info->flash_type == FLASH_TYPE_ROM) {
+ flash_getwidth(softc,info);
+ if (info->flash_type == FLASH_TYPE_FLASH) {
+ }
+ }
+}
+
+/* *********************************************************************
+ * flashdrv_setup_nvram(softc)
+ *
+ * If we're going to be using a sector of the flash for NVRAM,
+ * go find that sector and set it up.
+ *
+ * Input parameters:
+ * softc - our flash
+ *
+ * Return value:
+ * nothing. flashdrv_nvram_ok might change though.
+ ********************************************************************* */
+
+static void flashdrv_setup_nvram(flashdrv_t *softc)
+{
+ flash_sector_t sector;
+ int res;
+
+ softc->flashdrv_nvram_ok = FALSE;
+
+ if (softc->flashdrv_info.flash_type != FLASH_TYPE_FLASH) {
+ return;
+ }
+
+ sector.flash_sector_idx = 0;
+ for (;;) {
+ res = flash_sector_query(softc,&sector);
+ if (res == CFE_ERR_UNSUPPORTED) break;
+ if (res == 0) {
+ if (sector.flash_sector_status != FLASH_SECTOR_INVALID) {
+ sector.flash_sector_idx++;
+ continue;
+ }
+ }
+ break;
+ }
+
+ /* The sector offset will still contain the value at the end
+ of the last successful call. That's the last sector, so
+ we can now use this to fill in the NVRAM info structure */
+
+ if (res != CFE_ERR_UNSUPPORTED) {
+ softc->flashdrv_nvraminfo.nvram_offset = sector.flash_sector_offset;
+ softc->flashdrv_nvraminfo.nvram_size = sector.flash_sector_size;
+ softc->flashdrv_nvraminfo.nvram_eraseflg = TRUE; /* needs erase */
+ softc->flashdrv_nvram_ok = TRUE;
+ /*
+ * Set the flash's size as reported in the flash_info structure
+ * to be the size without the NVRAM sector at the end.
+ */
+ softc->flashdrv_info.flash_size = sector.flash_sector_offset;
+ softc->flashdrv_devsize = sector.flash_sector_offset;
+ }
+
+}
+
+
+/* *********************************************************************
+ * flashdrv_probe(drv,probe_a,probe_b,probe_ptr)
+ *
+ * Device probe routine. Attach the flash device to
+ * CFE's device table.
+ *
+ * Input parameters:
+ * drv - driver descriptor
+ * probe_a - physical address of flash
+ * probe_b - size of flash (bytes)
+ * probe_ptr - unused
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void flashdrv_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ flashdrv_t *softc;
+ flash_probe_t *probe;
+ char descr[80];
+
+ probe = (flash_probe_t *) probe_ptr;
+
+ /*
+ * probe_a is the flash base address
+ * probe_b is the size of the flash
+ * probe_ptr is unused.
+ */
+
+ softc = (flashdrv_t *) KMALLOC(sizeof(flashdrv_t),0);
+ if (softc) {
+ memset(softc,0,sizeof(flashdrv_t));
+
+ if (probe) {
+ /* Passed probe structure, do fancy stuff */
+ memcpy(&(softc->flashdrv_probe),probe,sizeof(flash_probe_t));
+ if (softc->flashdrv_probe.flash_prog_phys == 0) {
+ softc->flashdrv_probe.flash_prog_phys =
+ softc->flashdrv_probe.flash_phys;
+ }
+ }
+ else {
+ /* Didn't pass probe structure, do the compatible thing */
+ softc->flashdrv_probe.flash_phys = probe_a;
+ softc->flashdrv_probe.flash_prog_phys = probe_a;
+ softc->flashdrv_probe.flash_size = probe_b;
+ softc->flashdrv_probe.flash_flags = FLASH_FLG_NVRAM;
+ }
+
+ softc->flashdrv_cmdaddr = (char *) UNCADDR(softc->flashdrv_probe.flash_prog_phys);
+ softc->flashdrv_initialized = 0;
+ softc->flashdrv_ops = &FLASHOPS_DEFAULT;
+ xsprintf(descr,"%s at %08X size %uKB",drv->drv_description,
+ softc->flashdrv_probe.flash_phys,
+ softc->flashdrv_probe.flash_size/1024);
+ cfe_attach(drv,softc,NULL,descr);
+ }
+
+}
+
+
+/* *********************************************************************
+ * flashdrv_open(ctx)
+ *
+ * Called when the flash device is opened.
+ *
+ * Input parameters:
+ * ctx - device context
+ *
+ * Return value:
+ * 0 if ok else error code
+ ********************************************************************* */
+
+static int flashdrv_open(cfe_devctx_t *ctx)
+{
+ flashdrv_t *softc = ctx->dev_softc;
+
+ /*
+ * do initialization
+ */
+
+ if (!softc->flashdrv_initialized) {
+
+ /*
+ * Assume it's not an NVRAM-capable flash
+ */
+
+ softc->flashdrv_nvram_ok = FALSE;
+
+ /*
+ * Probe flash for geometry
+ */
+ flash_getinfo(softc);
+
+ /*
+ * Find the last sector if in NVRAM mode
+ */
+
+ if (softc->flashdrv_probe.flash_flags & FLASH_FLG_NVRAM) {
+ flashdrv_setup_nvram(softc);
+ }
+
+ softc->flashdrv_initialized = TRUE;
+ }
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * flashdrv_read(ctx,buffer)
+ *
+ * Read data from the flash device. The flash device is
+ * considered to be like a disk (you need to specify the offset).
+ *
+ * Input parameters:
+ * ctx - device context
+ * buffer - buffer descriptor
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+static int flashdrv_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ flashdrv_t *softc = ctx->dev_softc;
+ unsigned char *bptr;
+ unsigned char *flashbase;
+ int offset;
+ int blen;
+
+ /*
+ * For now, read the flash from K1 (always). Eventually
+ * we need to flush the cache after a write.
+ */
+
+ flashbase = (unsigned char *) UNCADDR(softc->flashdrv_probe.flash_phys);
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+ offset = (int) buffer->buf_offset;
+
+ if (!(softc->flashdrv_unlocked)) {
+ if ((offset + blen) > softc->flashdrv_devsize) {
+ blen = softc->flashdrv_devsize - offset;
+ }
+ }
+
+#ifdef _FLASH_BROKEN_BYTEREAD_
+ /*
+ * BCM1250 users: don't worry about this. This hack is for
+ * something else and should not be used with the BCM1250.
+ */
+ if (softc->flashdrv_probe.flash_flags & FLASH_FLG_16BIT) {
+ uint16_t *src;
+ int len = blen;
+ int idx = 0;
+ union {
+ uint16_t x;
+ char b[2];
+ } u;
+
+ src = (uint16_t *) flashbase;
+ while (len > 0) {
+ u.x = src[(idx+offset)>>1];
+ *bptr++ = u.b[(idx+offset)&1];
+ len--;
+ idx++;
+ }
+ }
+ else {
+ memcpy(bptr,flashbase + offset, blen);
+ }
+#else
+ memcpy(bptr,flashbase + offset, blen);
+#endif
+
+ buffer->buf_retlen = blen;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * flashdrv_inpstat(ctx,inpstat)
+ *
+ * Return "input status". For flash devices, we always return true.
+ *
+ * Input parameters:
+ * ctx - device context
+ * inpstat - input status structure
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+static int flashdrv_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
+{
+ /* flashdrv_t *softc = ctx->dev_softc; */
+
+ inpstat->inp_status = 1;
+ return 0;
+}
+
+
+/* *********************************************************************
+ * flash_writeall(softc,buffer)
+ *
+ * Write the entire flash and reboot. This is a special case
+ * used for when the flash currently being used for CFE's
+ * execution is updated. A small assembly routine is relocated
+ * to DRAM to do the update (so that the programming routine is
+ * not erased while we're running it), and then the update
+ * is done. When completed, CFE is restarted.
+ *
+ * (we could get really sleazy here and touch the routine first
+ * so it will stay in the cache, thereby eliminating the need
+ * to relocate it, but that's dangerous)
+ *
+ * Input parameters:
+ * softc - our context
+ * buffer - buffer descriptor
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+static int flash_writeall(flashdrv_t *softc,iocb_buffer_t *buffer)
+{
+ void *rptr;
+ void (*routine)(unsigned char *data,unsigned int flashbase,
+ unsigned int size,unsigned int secsize);
+
+ rptr = KMALLOC(flash_write_all_len,0);
+
+ if (!rptr) return CFE_ERR_NOMEM;
+
+ memcpy(rptr,flash_write_all_ptr,flash_write_all_len);
+
+ _cfe_flushcache(0);
+
+ routine = rptr;
+
+ (*routine)(buffer->buf_ptr,
+ softc->flashdrv_probe.flash_phys,
+ buffer->buf_length,
+ 65536);
+
+ return -1;
+}
+
+
+/* *********************************************************************
+ * flashdrv_write(ctx,buffer)
+ *
+ * Write data to the flash device. The flash device is
+ * considered to be like a disk (you need to specify the offset).
+ *
+ * Input parameters:
+ * ctx - device context
+ * buffer - buffer descriptor
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+static int flashdrv_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ flashdrv_t *softc = ctx->dev_softc;
+ unsigned char *bptr;
+ int offset;
+ int blen;
+ int res;
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+ offset = (int) buffer->buf_offset;
+
+ if (!(softc->flashdrv_unlocked)) {
+ if ((offset + blen) > softc->flashdrv_devsize) {
+ blen = softc->flashdrv_devsize - offset;
+ }
+ }
+
+ res = FLASHOP_WRITE_BLOCK(softc,offset,bptr,blen);
+
+ buffer->buf_retlen = res;
+
+ /* XXX flush the cache here? */
+
+ return (res == blen) ? 0 : CFE_ERR_IOERR;
+}
+
+/* *********************************************************************
+ * flashdrv_ioctl(ctx,buffer)
+ *
+ * Handle special IOCTL functions for the flash. Flash devices
+ * support NVRAM information, sector and chip erase, and a
+ * special IOCTL for updating the running copy of CFE.
+ *
+ * Input parameters:
+ * ctx - device context
+ * buffer - descriptor for IOCTL parameters
+ *
+ * Return value:
+ * 0 if ok else error
+ ********************************************************************* */
+static int flashdrv_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ flashdrv_t *softc = ctx->dev_softc;
+ nvram_info_t *info;
+ int offset;
+
+ /*
+ * If using flash to store environment, only the last sector
+ * is used for environment stuff.
+ */
+
+ switch ((int)buffer->buf_ioctlcmd) {
+ case IOCTL_NVRAM_ERASE:
+ if (softc->flashdrv_nvram_ok == FALSE) return CFE_ERR_UNSUPPORTED;
+ FLASHOP_ERASE_SECTOR(softc,softc->flashdrv_nvraminfo.nvram_offset);
+ return 0;
+
+ case IOCTL_NVRAM_GETINFO:
+ info = (nvram_info_t *) buffer->buf_ptr;
+ if (buffer->buf_length != sizeof(nvram_info_t)) return CFE_ERR_INV_PARAM;
+ if (softc->flashdrv_nvram_ok == FALSE) return CFE_ERR_UNSUPPORTED;
+ info->nvram_offset = softc->flashdrv_nvraminfo.nvram_offset;
+ info->nvram_size = softc->flashdrv_nvraminfo.nvram_size;
+ info->nvram_eraseflg = softc->flashdrv_nvraminfo.nvram_eraseflg;
+ buffer->buf_retlen = sizeof(nvram_info_t);
+ return 0;
+
+ case IOCTL_FLASH_ERASE_SECTOR:
+ offset = (int) buffer->buf_offset;
+ if (!(softc->flashdrv_unlocked)) {
+ if (offset >= softc->flashdrv_devsize) return -1;
+ }
+ FLASHOP_ERASE_SECTOR(softc,offset);
+ return 0;
+
+ case IOCTL_FLASH_ERASE_ALL:
+ offset = (int) buffer->buf_offset;
+ if (offset != 0) return -1;
+ flash_erase_all(softc);
+ return 0;
+
+ case IOCTL_FLASH_WRITE_ALL:
+ flash_writeall(softc,buffer);
+ return -1; /* should not return */
+
+ case IOCTL_FLASH_GETINFO:
+ memcpy(buffer->buf_ptr,&(softc->flashdrv_info),sizeof(flash_info_t));
+ return 0;
+
+ case IOCTL_FLASH_GETSECTORS:
+ return flash_sector_query(softc,(flash_sector_t *) buffer->buf_ptr);
+
+
+ case IOCTL_FLASH_ERASE_RANGE:
+ return flash_erase_range(softc,(flash_range_t *) buffer->buf_ptr);
+
+ case IOCTL_NVRAM_UNLOCK:
+ softc->flashdrv_unlocked = TRUE;
+ break;
+
+ default:
+ return -1;
+ }
+
+ return -1;
+}
+
+
+/* *********************************************************************
+ * flashdrv_close(ctx)
+ *
+ * Close the flash device.
+ *
+ * Input parameters:
+ * ctx - device context
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+static int flashdrv_close(cfe_devctx_t *ctx)
+{
+ /* flashdrv_t *softc = ctx->dev_softc; */
+
+ /* XXX Invalidate the cache */
+
+ return 0;
+}
+
+
diff --git a/cfe/cfe/dev/dev_ht7520.c b/cfe/cfe/dev/dev_ht7520.c
new file mode 100644
index 0000000..8e64971
--- /dev/null
+++ b/cfe/cfe/dev/dev_ht7520.c
@@ -0,0 +1,167 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * HT7520 (Golem) Bridge Support File: dev_ht7520.c
+ *
+ *********************************************************************
+ *
+ * Copyright 2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_physio.h"
+
+#include "pcireg.h"
+#include "pcivar.h"
+
+extern int eoi_implemented;
+
+void ht7520apic_preset (pcitag_t tag);
+void ht7520apic_setup (pcitag_t tag);
+
+
+/* PLX HT7520 (LDT to PCI-X bridge + APIC) specific definitions */
+
+#define PCI_VENDOR_AMD 0x1022
+#define PCI_PRODUCT_PLX_HT7520 0x7450
+#define PCI_PRODUCT_PLX_HT7520_APIC 0x7451
+
+/* HT7520 specific registers */
+
+/* APIC configuration registers */
+
+#define APIC_CONTROL_REG 0x0044
+
+#define APIC_CONTROL_OSVISBAR (1 << 0)
+#define APIC_CONTROL_IOAEN (1 << 1)
+
+#define APIC_BASE_ADDR_REG 0x0048
+
+/* APIC registers in BAR0 memory space */
+
+#define HT7520_APIC_INDEX_REG 0x0000
+#define HT7520_APIC_DATA_REG 0x0010
+
+#define APIC_ID_INDEX 0x00
+#define APIC_VERSION_INDEX 0x01
+#define APIC_ARBID_INDEX 0x02
+#define APIC_RDR_BASE_INDEX 0x10
+#define APIC_RDR_LO_INDEX(n) (APIC_RDR_BASE_INDEX + 2*(n))
+#define APIC_RDR_HI_INDEX(n) (APIC_RDR_BASE_INDEX + 2*(n) + 1)
+
+#define RDR_HI_DEST_SHIFT (56-32)
+#define RDR_HI_DEST_MASK (0xff << RDR_HI_DEST_SHIFT)
+#define RDR_LO_IM (1 << 16)
+#define RDR_LO_TM (1 << 15)
+#define RDR_LO_IRR (1 << 14)
+#define RDR_LO_POL (1 << 13)
+#define RDR_LO_DS (1 << 12)
+#define RDR_LO_DM (1 << 11)
+#define RDR_LO_MT_SHIFT 8
+#define RDR_LO_MT_MASK (3 << RDR_LO_MT_SHIFT)
+#define RDR_LO_IV_SHIFT 0
+#define RDR_LO_IV_MASK (0xff << RDR_LO_IV_SHIFT)
+
+void
+ht7520apic_preset (pcitag_t tag)
+{
+ pcireg_t ctrl;
+
+ /* For some reason, BAR0 (necessary for setting the interrupt
+ mapping) is hidden by default; the following makes it
+ visible. */
+ ctrl = pci_conf_read(tag, APIC_CONTROL_REG);
+ ctrl |= APIC_CONTROL_IOAEN | APIC_CONTROL_OSVISBAR;
+ pci_conf_write(tag, APIC_CONTROL_REG, ctrl);
+ ctrl = pci_conf_read(tag, APIC_CONTROL_REG); /* push */
+}
+
+void
+ht7520apic_setup (pcitag_t tag)
+{
+ int bus, device, function;
+ pcitag_t br_tag;
+ int secondary;
+ struct pci_bus *pb;
+ unsigned offset;
+ phys_addr_t apic_addr;
+ uint32_t rdrh, rdrl;
+ int i;
+
+ /* The HT7520 splits the bridge and APIC functionality between two
+ functions. The following code depends upon a known
+ relationship between the bridge and APIC tags, with a temporary
+ fudge for the simulator. NB: We assume that the bridge
+ function has already been initialized. */
+
+ pci_break_tag(tag, &bus, &device, &function);
+
+#ifdef _FUNCSIM_
+ br_tag = pci_make_tag(bus, device-2, 0);
+#else
+ br_tag = pci_make_tag(bus, device, function-1);
+#endif
+ secondary = (pci_conf_read(br_tag, PPB_BUSINFO_REG) >> 8) & 0xff;
+ pb = &_pci_bus[secondary];
+
+ /* Set up interrupt mappings. */
+ pci_map_mem(tag, PCI_MAPREG(0), PCI_MATCH_BITS, &apic_addr);
+
+ offset = pb->inta_shift % 4;
+ for (i = 0; i < 4; i++) {
+ phys_write32(apic_addr + HT7520_APIC_INDEX_REG, APIC_RDR_HI_INDEX(i));
+ rdrh = 0x03 << RDR_HI_DEST_SHIFT; /* CPU 0 + CPU 1 */
+ phys_write32(apic_addr + HT7520_APIC_DATA_REG, rdrh);
+ rdrh = phys_read32(apic_addr + HT7520_APIC_DATA_REG); /* push */
+
+ phys_write32(apic_addr + HT7520_APIC_INDEX_REG, APIC_RDR_LO_INDEX(i));
+ if (eoi_implemented) {
+ /* Passes >=2 have working EOI. Trigger=Level */
+ rdrl = (RDR_LO_TM | /* Level */
+ RDR_LO_POL | /* Active Low */
+ RDR_LO_DM | /* Logical */
+ 0x0 << RDR_LO_MT_SHIFT | /* Fixed */
+ (56+offset) << RDR_LO_IV_SHIFT); /* Vector */
+ } else {
+ /* Pass 1 lacks working EOI. Trigger=Edge. Note that
+ LO_POL appears mis-documented for edges. */
+ rdrl = (RDR_LO_DM | /* Logical */
+ 0x0 << RDR_LO_MT_SHIFT | /* Fixed */
+ (56+offset) << RDR_LO_IV_SHIFT); /* Vector */
+ }
+ phys_write32(apic_addr + HT7520_APIC_DATA_REG, rdrl);
+ offset = (offset + 1) % 4;
+ }
+}
diff --git a/cfe/cfe/dev/dev_ide_common.c b/cfe/cfe/dev/dev_ide_common.c
new file mode 100644
index 0000000..e15ac8a
--- /dev/null
+++ b/cfe/cfe/dev/dev_ide_common.c
@@ -0,0 +1,1249 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Generic IDE disk driver File: dev_ide_common.c
+ *
+ * This is a simple driver for IDE hard disks. The mechanics
+ * of talking to the I/O ports are abstracted sufficiently to make
+ * this driver usable for various bus interfaces.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "cfe_timer.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+#include "cfe_error.h"
+
+#include "dev_ide_common.h"
+
+#include "dev_ide.h"
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define DISK_MASTER 0
+#define DISK_SLAVE 1
+
+#define IDE_WRITEREG8(ide,reg,val) IDEDISP_WRITEREG8(ide->idecommon_dispatch,reg,val)
+#define IDE_WRITEREG16(ide,reg,val) IDEDISP_WRITEREG8(ide->idecommon_dispatch,reg,val)
+#define IDE_WRITEBUF(ide,reg,buf,len) IDEDISP_WRITEBUF(ide->idecommon_dispatch,reg,buf,len)
+#define IDE_READREG8(ide,reg) IDEDISP_READREG8(ide->idecommon_dispatch,reg)
+#define IDE_READREG16(ide,reg) IDEDISP_READREG16(ide->idecommon_dispatch,reg)
+#define IDE_READBUF(ide,reg,buf,len) IDEDISP_READBUF(ide->idecommon_dispatch,reg,buf,len)
+
+#define GETWORD_LE(buf,wordidx) (((unsigned int) (buf)[(wordidx)*2]) + \
+ (((unsigned int) (buf)[(wordidx)*2+1]) << 8))
+
+#define _IDE_DEBUG_
+
+
+static void idecommon_testdrq(idecommon_t *ide);
+
+/* *********************************************************************
+ * idecommon_sectorshift(size)
+ *
+ * Given a sector size, return log2(size). We cheat; this is
+ * only needed for 2048 and 512-byte sectors.
+ * Explicitly using shifts and masks in sector number calculations
+ * helps on 32-bit-only platforms, since we probably won't need
+ * a helper library.
+ *
+ * Input parameters:
+ * size - sector size
+ *
+ * Return value:
+ * # of bits to shift
+ ********************************************************************* */
+
+#define idecommon_sectorshift(size) (((size)==2048)?11:9)
+
+/* *********************************************************************
+ * idecommon_waitnotbusy(ide)
+ *
+ * Wait for an IDE device to report "not busy"
+ *
+ * Input parameters:
+ * ide - IDE interface
+ *
+ * Return value:
+ * 0 if ok, else -1 if timeout
+ ********************************************************************* */
+
+static int idecommon_waitnotbusy(idecommon_t *ide)
+{
+ int32_t timer;
+ uint8_t status;
+
+ TIMER_SET(timer,10*CFE_HZ);
+
+ while (!TIMER_EXPIRED(timer)) {
+ status = IDE_READREG8(ide,IDE_REG_STATUS);
+ if (!(status & IDE_STS_BSY) && (status & IDE_STS_DRQ)) {
+ idecommon_testdrq(ide);
+ continue;
+ }
+ if ((status & (IDE_STS_BSY | IDE_STS_DRQ )) == 0) return 0;
+ POLL();
+ }
+
+#ifdef _IDE_DEBUG_
+ xprintf("Device did not become unbusy\n");
+#endif
+ return -1;
+}
+
+#if 0
+/* *********************************************************************
+ * idecommon_waitready(ide)
+ *
+ * Wait for the specified device to become ready.
+ *
+ * Input parameters:
+ * ide - IDE interface
+ *
+ * Return value:
+ * 0 if device became ready
+ * -1 if device did not become ready
+ ********************************************************************* */
+
+static int idecommon_waitready(idecommon_t *ide)
+{
+ int32_t timer;
+ uint8_t status;
+
+ TIMER_SET(timer,10*CFE_HZ);
+
+ while (!TIMER_EXPIRED(timer)) {
+ status = IDE_READREG8(ide,IDE_REG_STATUS);
+ if (status & IDE_STS_RDY) return 0;
+ POLL();
+ }
+
+#ifdef _IDE_DEBUG_
+ xprintf("Disk did not become ready\n");
+#endif
+
+ return -1;
+}
+#endif
+
+/* *********************************************************************
+ * idecommon_waitbusy(idx)
+ *
+ * Wait for an IDE disk to start processing a command, or at
+ * least long enough to indicate that it is doing so.
+ * The code below looks suspiciously like a timing loop.
+ * unfortunately, that's what it is, determined empirically
+ * for certain ATA flash cards. Without this many reads to the
+ * ALTSTAT register, the PCMCIA controller deasserts the
+ * card detect pins briefly. Anyone have any clues?
+ *
+ * Input parameters:
+ * ide - IDE interface
+ *
+ * Return value:
+ * void
+ ********************************************************************* */
+
+static void idecommon_waitbusy(idecommon_t *ide)
+{
+ int idx;
+
+ for (idx = 0; idx < 10; idx++) {
+ IDE_READREG8(ide,IDE_REG_ALTSTAT);
+ IDE_READREG8(ide,IDE_REG_ALTSTAT);
+ IDE_READREG8(ide,IDE_REG_ALTSTAT);
+ IDE_READREG8(ide,IDE_REG_ALTSTAT);
+ }
+}
+
+
+/* *********************************************************************
+ * idecommon_wait_drq(ide)
+ *
+ * Wait for the BUSY bit to be clear and the DRQ bit to be set.
+ * This is usually the indication that it's time to transfer data.
+ *
+ * Input parameters:
+ * ide - IDE interface
+ * 0 if DRQ is set
+ * -1 if timeout occured
+ ********************************************************************* */
+
+static int idecommon_wait_drq(idecommon_t *ide)
+{
+ int32_t timer;
+ uint8_t status;
+
+ TIMER_SET(timer,10*CFE_HZ);
+
+ while (!TIMER_EXPIRED(timer)) {
+ POLL();
+ status = IDE_READREG8(ide,IDE_REG_STATUS);
+ if (!(status & IDE_STS_BSY) && (status & IDE_STS_ERR)) {
+ xprintf("Drive status: %02X error %02X\n",status,
+ IDE_READREG8(ide,IDE_REG_ERROR));
+ return -1;
+ }
+ if (!(status & IDE_STS_BSY) && (status & IDE_STS_DRQ)) return 0;
+ }
+
+#ifdef _IDE_DEBUG_
+ xprintf("Timeout waiting for disk\n");
+#endif
+
+ return -1;
+}
+
+/* *********************************************************************
+ * idecommon_testdrq(ide)
+ *
+ * Debug routine. Check the DRQ bit. If it's set, it is not
+ * supposed to be, so transfer data until it clears and report
+ * how much we had to transfer.
+ *
+ * Input parameters:
+ * ide - IDE interface
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+#ifdef _IDE_DEBUG_
+static void idecommon_testdrq(idecommon_t *ide)
+{
+ uint8_t status;
+ uint16_t data;
+ int idx;
+
+ status = IDE_READREG8(ide,IDE_REG_STATUS);
+ if (status & IDE_STS_DRQ) {
+ xprintf("Error: DRQ should be zero\n");
+ idx = 0;
+ while (status & IDE_STS_DRQ) {
+ data = IDE_READREG16(ide,IDE_REG_DATA);
+ idx++;
+ status = IDE_READREG8(ide,IDE_REG_STATUS);
+ }
+ xprintf("Had to read data %d times to clear DRQ\n",idx);
+ }
+}
+#else
+#define idecommon_testdrq(ide)
+#endif
+
+
+/* *********************************************************************
+ * idecommon_dumpregs(ide)
+ *
+ * Dump out the IDE registers. (debug routine)
+ *
+ * Input parameters:
+ * ide - ide disk
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void idecommon_dumpregs(idecommon_t *ide)
+{
+#if 0
+ uint8_t reg = 0;
+
+ reg = IDE_READREG8(ide,IDE_REG_STATUS);
+ xprintf("Status:%02X ",reg);
+
+ reg = IDE_READREG8(ide,IDE_REG_DRVHD);
+ xprintf("DrvHd:%02X ",reg);
+
+ reg = IDE_READREG8(ide,IDE_REG_CYLLSB);
+ xprintf("CylLSB:%02X ",reg);
+
+ reg = IDE_READREG8(ide,IDE_REG_CYLMSB);
+ xprintf("CylMSB:%02X ",reg);
+
+ reg = IDE_READREG8(ide,IDE_REG_SECNUM);
+ xprintf("SecNum:%02X ",reg);
+
+ reg = IDE_READREG8(ide,IDE_REG_SECCNT);
+ xprintf("SecCnt:%02X ",reg);
+
+ xprintf("\n");
+#endif
+}
+
+
+/* *********************************************************************
+ * idecommon_reset(ide)
+ *
+ * Reset the IDE interface.
+ *
+ * Input parameters:
+ * ide - IDE interface
+ *
+ * Return value:
+ * 0 if ok, else -1 if a timeout occured
+ ********************************************************************* */
+
+static int idecommon_reset(idecommon_t *ide)
+{
+ return 0;
+}
+
+/* *********************************************************************
+ * idecommon_identify(ide,buffer)
+ *
+ * Execute an IDENTIFY command to get information about the disk.
+ *
+ * Input parameters:
+ * ide - IDE interface
+ * buffer - pointer to 512 byte buffer
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int idecommon_identify(idecommon_t *ide,unsigned char *buffer)
+{
+
+ /* Device Select Protocol; see ATAPI-4 sect 9.6 */
+
+ if (idecommon_waitnotbusy(ide) < 0) return -1;
+ IDE_WRITEREG8(ide,IDE_REG_DRVHD,(ide->idecommon_unit<<4)|0);
+ if (idecommon_waitnotbusy(ide) < 0) return -1;
+
+ /* Set device registers */
+
+ IDE_WRITEREG8(ide,IDE_REG_CYLLSB,0);
+ IDE_WRITEREG8(ide,IDE_REG_CYLMSB,0);
+ IDE_WRITEREG8(ide,IDE_REG_SECNUM,1);
+ IDE_WRITEREG8(ide,IDE_REG_SECCNT,1);
+
+ idecommon_testdrq(ide);
+
+ /* Issue command, then read ALT STATUS (9.7) */
+
+ if (ide->idecommon_atapi) {
+ IDE_WRITEREG8(ide,IDE_REG_COMMAND,IDE_CMD_ATAPI_IDENTIFY);
+ }
+ else {
+ IDE_WRITEREG8(ide,IDE_REG_COMMAND,IDE_CMD_DRIVE_INFO);
+ }
+
+ IDE_READREG8(ide,IDE_REG_ALTSTAT);
+ idecommon_waitbusy(ide); /* should not be necessary */
+
+ /* Wait BSY=0 && DRQ=1, then read buffer, see sect 9.7 */
+
+ if (idecommon_wait_drq(ide) < 0) return -1;
+ IDE_READBUF(ide,IDE_REG_DATA,buffer,DISK_SECTORSIZE);
+
+ idecommon_testdrq(ide);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * idecommon_packet(ide,packet,pktlen,databuf,datalen)
+ *
+ * Process an IDE "packet" command, for ATAPI devices
+ *
+ * Input parameters:
+ * ide - IDE interface
+ * packet,pktlen - command packet
+ * databuf,datalen - data buffer
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int idecommon_packet(idecommon_t *ide,
+ uint8_t *packet,int pktlen,
+ uint8_t *databuf,int datalen)
+{
+ uint8_t status;
+
+ /*
+ * Not valid on non-ATAPI disks
+ */
+
+ if (!ide->idecommon_atapi) return -1;
+
+ /*
+ * Set up the standard IDE registers for an ATAPI PACKET command
+ */
+
+ /* Device Select Protocol */
+ if (idecommon_waitnotbusy(ide) < 0) return -1;
+ IDE_WRITEREG8(ide,IDE_REG_DRVHD,(ide->idecommon_unit<<4));
+ if (idecommon_waitnotbusy(ide) < 0) return -1;
+
+ /* Device Registers */
+ IDE_WRITEREG8(ide,IDE_REG_BCLSB,(datalen & 0xFF));
+ IDE_WRITEREG8(ide,IDE_REG_BCMSB,((datalen >> 8) & 0xFF));
+ IDE_WRITEREG8(ide,IDE_REG_SECNUM,0);
+ IDE_WRITEREG8(ide,IDE_REG_SECCNT,0);
+ IDE_WRITEREG8(ide,IDE_REG_COMMAND,IDE_CMD_ATAPI_PACKET);
+
+ /*
+ * Wait for the DRQ bit to indicate that we should send
+ * the packet.
+ */
+
+ if (idecommon_wait_drq(ide) < 0) return -1;
+
+ status = IDE_READREG8(ide,IDE_REG_IR);
+
+ /*
+ * Send the packet to the device
+ */
+
+ IDE_WRITEBUF(ide,IDE_REG_DATA,packet,pktlen);
+
+ /*
+ * Wait for BSY to be cleared and DRQ to be set.
+ */
+
+ if (idecommon_wait_drq(ide) < 0) return -1;
+ status = IDE_READREG8(ide,IDE_REG_ALTSTAT);
+ if (idecommon_wait_drq(ide) < 0) return -1;
+ status = IDE_READREG8(ide,IDE_REG_IR);
+
+
+ /*
+ * Transfer data, if necessary. The direction will depend
+ * on what the drive says. If this is a non-data command,
+ * passing databuf == NULL can avoid all this.
+ */
+
+ if (databuf) {
+ status = IDE_READREG8(ide,IDE_REG_IR);
+ if (status & IDE_IR_CD) {
+ xprintf("Error: Command/data should be zero\n");
+ }
+
+ if (status & IDE_IR_IO) { /* from device (READ) */
+ IDE_READBUF(ide,IDE_REG_DATA,databuf,datalen);
+ }
+ else { /* to device (WRITE) */
+ IDE_WRITEBUF(ide,IDE_REG_DATA,databuf,datalen);
+ }
+
+ }
+
+
+ idecommon_testdrq(ide);
+
+ return 0;
+
+}
+
+
+/* *********************************************************************
+ * idecommon_request_sense(ide)
+ *
+ * Request sense data. This also clears a UNIT_ATTENTION condition
+ *
+ * Input parameters:
+ * ide - IDE interface
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+static int idecommon_request_sense(idecommon_t *ide)
+{
+ uint8_t cdb[12];
+ uint8_t sensedata[32];
+ int res;
+ int numbytes;
+
+ numbytes = sizeof(sensedata);
+
+ cdb[0] = CDB_CMD_REQSENSE;
+ cdb[1] = 0;
+ cdb[2] = 0;
+ cdb[3] = 0;
+ cdb[4] = sizeof(sensedata);
+ cdb[5] = 0;
+ cdb[6] = 0;
+ cdb[7] = 0;
+ cdb[8] = 0;
+ cdb[9] = 0;
+ cdb[10] = 0;
+ cdb[11] = 0;
+
+ memset(sensedata,0,sizeof(sensedata));
+
+ res = idecommon_packet(ide,cdb,sizeof(cdb),sensedata,numbytes);
+
+#if 0
+ xprintf("Sense data: ");
+ xprintf("Err:%02X ",sensedata[0]);
+ xprintf("Key:%02X ",sensedata[1]);
+ xprintf("Information:%02X%02X ",sensedata[2],sensedata[3]);
+ xprintf("ASC:%02X ASCQ:%02X ",sensedata[12],sensedata[13]);
+ xprintf("\n");
+#endif
+
+ idecommon_testdrq(ide);
+
+ return res;
+}
+
+
+/* *********************************************************************
+ * idecommon_read_atapi(ide,lba,numsec,buffer)
+ *
+ * Read sector(s) from the device. This version is for ATAPI devs.
+ *
+ * Input parameters:
+ * ide - IDE interface
+ * lba - logical block address
+ * numsec - number of sectors
+ * buffer - buffer address
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int idecommon_read_atapi(idecommon_t *ide,uint64_t lba,
+ int numsec,unsigned char *buffer)
+{
+ uint8_t cdb[12];
+ int res = 0;
+ int numbytes;
+ int idx;
+
+ numbytes = numsec << idecommon_sectorshift(ide->idecommon_sectorsize);
+
+ cdb[0] = CDB_CMD_READ;
+ cdb[1] = 0;
+ cdb[2] = ((lba >> 24) & 0xFF);
+ cdb[3] = ((lba >> 16) & 0xFF);
+ cdb[4] = ((lba >> 8) & 0xFF);
+ cdb[5] = ((lba >> 0) & 0xFF);
+ cdb[6] = 0;
+ cdb[7] = ((numsec >> 8) & 0xFF);
+ cdb[8] = ((numsec >> 0) & 0xFF);
+ cdb[9] = 0;
+ cdb[10] = 0;
+ cdb[11] = 0;
+
+ for (idx = 0; idx < 4; idx++) {
+ res = idecommon_packet(ide,cdb,sizeof(cdb),buffer,numbytes);
+ if (res < 0) {
+ idecommon_request_sense(ide);
+ continue;
+ }
+ break;
+ }
+
+ return res;
+}
+
+
+/* *********************************************************************
+ * idecommon_write_atapi(ide,lba,numsec,buffer)
+ *
+ * Write sector(s) to the device. This version is for ATAPI disks
+ *
+ * Input parameters:
+ * ide - IDE interface
+ * lba - logical block address
+ * numsec - number of sectors
+ * buffer - buffer address
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int idecommon_write_atapi(idecommon_t *ide,uint64_t lba,
+ int numsec,unsigned char *buffer)
+{
+ uint8_t cdb[12];
+ int res;
+ int numbytes;
+
+ numbytes = numsec << idecommon_sectorshift(ide->idecommon_sectorsize);
+
+ cdb[0] = CDB_CMD_WRITE;
+ cdb[1] = 0;
+ cdb[2] = ((lba >> 24) & 0xFF);
+ cdb[3] = ((lba >> 16) & 0xFF);
+ cdb[4] = ((lba >> 8) & 0xFF);
+ cdb[5] = ((lba >> 0) & 0xFF);
+ cdb[6] = 0;
+ cdb[7] = ((numsec >> 8) & 0xFF);
+ cdb[8] = ((numsec >> 0) & 0xFF);
+ cdb[9] = 0;
+ cdb[10] = 0;
+ cdb[11] = 0;
+
+ res = idecommon_packet(ide,cdb,sizeof(cdb),buffer,numbytes);
+
+ return res;
+}
+
+
+/* *********************************************************************
+ * idecommon_read_lba(ide,lba,numsec,buffer)
+ *
+ * Read sector(s) from the device.
+ *
+ * Input parameters:
+ * ide - IDE interface
+ * lba - logical block address
+ * numsec - number of sectors
+ * buffer - buffer address
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int idecommon_read_lba(idecommon_t *ide,uint64_t lba,int numsec,unsigned char *buffer)
+{
+ int secidx;
+ unsigned char *ptr;
+
+ if (idecommon_waitnotbusy(ide) < 0) return -1;
+ IDE_WRITEREG8(ide,IDE_REG_DRVHD,(ide->idecommon_unit<<4) | ((lba >> 24) & 0x0F) | 0x40);
+ if (idecommon_waitnotbusy(ide) < 0) return -1;
+
+ IDE_WRITEREG8(ide,IDE_REG_CYLMSB,((lba >> 16) & 0xFF));
+ IDE_WRITEREG8(ide,IDE_REG_CYLLSB,((lba >> 8) & 0xFF));
+ IDE_WRITEREG8(ide,IDE_REG_SECNUM,(lba & 0xFF));
+ IDE_WRITEREG8(ide,IDE_REG_SECCNT,numsec);
+
+ idecommon_testdrq(ide);
+
+ IDE_WRITEREG8(ide,IDE_REG_COMMAND,IDE_CMD_READ);
+
+ idecommon_waitbusy(ide);
+ if (idecommon_wait_drq(ide) < 0) return -1;
+
+ ptr = buffer;
+
+ for (secidx = 0; secidx < numsec; secidx++) {
+ IDE_READBUF(ide,IDE_REG_DATA,ptr,ide->idecommon_sectorsize);
+ ptr += ide->idecommon_sectorsize;
+ }
+
+ idecommon_testdrq(ide);
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * idecommon_write_lba(ide,lba,numsec,buffer)
+ *
+ * Write sector(s) from the device.
+ *
+ * Input parameters:
+ * ide - IDE interface
+ * lba - logical block address
+ * numsec - number of sectors
+ * buffer - buffer address
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int idecommon_write_lba(idecommon_t *ide,uint64_t lba,int numsec,unsigned char *buffer)
+{
+ int secidx;
+ uint8_t *ptr;
+
+ if (idecommon_waitnotbusy(ide) < 0) return -1;
+ IDE_WRITEREG8(ide,IDE_REG_DRVHD,(ide->idecommon_unit<<4) | ((lba >> 24) & 0x0F) | 0x40);
+ if (idecommon_waitnotbusy(ide) < 0) return -1;
+
+ IDE_WRITEREG8(ide,IDE_REG_CYLMSB,((lba >> 16) & 0xFF));
+ IDE_WRITEREG8(ide,IDE_REG_CYLLSB,((lba >> 8) & 0xFF));
+ IDE_WRITEREG8(ide,IDE_REG_SECNUM,(lba & 0xFF));
+ IDE_WRITEREG8(ide,IDE_REG_SECCNT,numsec);
+
+ IDE_WRITEREG8(ide,IDE_REG_COMMAND,IDE_CMD_WRITE);
+
+ if (idecommon_wait_drq(ide) < 0) return -1;
+
+ ptr = buffer;
+
+ for (secidx = 0; secidx < numsec; secidx++) {
+ IDE_WRITEBUF(ide,IDE_REG_DATA,ptr,ide->idecommon_sectorsize);
+ ptr += ide->idecommon_sectorsize;
+ }
+
+ idecommon_testdrq(ide);
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * idecommon_diagnostic(ide)
+ *
+ * run the device diagnostics on the IDE device. This also
+ * helps us determine if it's an IDE or ATAPI disk, since the
+ * diagnostic will leave a signature in the registers.
+ *
+ * Input parameters:
+ * softc - IDE interface
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int idecommon_diagnostic(idecommon_t *softc)
+{
+ if (idecommon_waitnotbusy(softc) < 0) return -1;
+ IDE_WRITEREG8(softc,IDE_REG_DRVHD,(softc->idecommon_unit<<4));
+ if (idecommon_waitnotbusy(softc) < 0) return -1;
+
+ IDE_WRITEREG8(softc,IDE_REG_COMMAND,IDE_CMD_DIAGNOSTIC);
+ if (idecommon_waitnotbusy(softc) < 0) return -1;
+
+ cfe_sleep(CFE_HZ/2);
+ idecommon_dumpregs(softc);
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * idecommon_getmodel(buffer,model)
+ *
+ * Get the ASCII model name out of an IDE identify buffer. some
+ * byte swapping is involved here. The trailing blanks are trimmed.
+ *
+ * Input parameters:
+ * buffer - 512-byte buffer from IDENTIFY command
+ * model - 41-byte string (max) for model name
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void idecommon_getmodel(uint8_t *buffer,char *model)
+{
+ uint16_t w;
+ int idx;
+
+ for (idx = 0; idx < 20; idx++) {
+ w = GETWORD_LE(buffer,27+idx);
+ model[idx*2] = w >> 8;
+ model[idx*2+1] = w & 0xFF;
+ }
+ for (idx = 39; idx > 0; idx--) {
+ if (model[idx] != ' ') {
+ model[idx+1] = '\0';
+ break;
+ }
+ }
+
+}
+
+/* *********************************************************************
+ * idecommon_devprobe(softc)
+ *
+ * Probe the IDE device, to determine if it's actually present
+ * or not. If present, determine if it's IDE or ATAPI and
+ * get the device size. Init our internal structures so we know
+ * how to talk to the device.
+ *
+ * Input parameters:
+ * softc - IDE structure
+ * noisy - display stuff as we probe
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+int idecommon_devprobe(idecommon_t *softc,int noisy)
+{
+ int res;
+ int atapi;
+ unsigned char buffer[DISK_SECTORSIZE];
+ unsigned char model[41];
+ uint64_t ttlsect;
+ int devtype;
+ uint16_t w;
+ char *typename;
+
+ /*
+ * Reset the drive
+ */
+
+ res = idecommon_reset(softc);
+ if (res < 0) return -1;
+
+ /*
+ * Run diagnostic to get the signature.
+ */
+
+ res = idecommon_diagnostic(softc);
+ if (res < 0) return res;
+
+ /*
+ * Test signature
+ */
+
+ atapi = 0;
+ if ((IDE_READREG8(softc,IDE_REG_CYLLSB) == ATAPI_SIG_LSB) &&
+ (IDE_READREG8(softc,IDE_REG_CYLMSB) == ATAPI_SIG_MSB)) {
+ atapi = 1;
+ }
+
+ if (noisy) {
+ if (atapi) xprintf("ATAPI: ");
+ else xprintf("IDE: ");
+ }
+
+ /*
+ * Do tha appropriate IDENTIFY command to get device information
+ */
+
+ softc->idecommon_atapi = atapi;
+ res = idecommon_identify(softc,buffer);
+ if (res < 0) return -1;
+
+ /*
+ * Using that information, determine our device type
+ */
+
+ if (!atapi) {
+ devtype = IDE_DEVTYPE_DISK;
+ typename = "Disk";
+ }
+ else {
+ w = GETWORD_LE(buffer,0);
+ switch ((w >> 8) & 31) {
+ case 5: /* CD-ROM */
+ devtype = IDE_DEVTYPE_CDROM;
+ typename = "CD-ROM";
+ break;
+ default:
+ devtype = IDE_DEVTYPE_ATAPIDISK;
+ typename = "Disk";
+ break;
+ }
+ }
+
+ /*
+ * Say nice things about the device.
+ */
+
+ idecommon_getmodel(buffer,model);
+ if (noisy) xprintf("%s, \"%s\"",typename,model);
+
+
+#ifdef _IDE_DEBUG_
+ if (!softc->idecommon_atapi) {
+ ttlsect = (GETWORD_LE(buffer,57) + (GETWORD_LE(buffer,58) << 16));
+ if (noisy) xprintf(", Sectors: %llu (%lld MB)",ttlsect,
+ (uint64_t) (ttlsect/2048));
+ }
+ else {
+ ttlsect = 0;
+ }
+#endif
+ if (noisy) xprintf("\n");
+
+ /*
+ * Initialize internal structure info, especially pointers to the
+ * read/write routines and the sector size.
+ */
+
+ softc->idecommon_ttlsect = ttlsect;
+ idecommon_init(softc,devtype);
+
+ return res;
+}
+
+/* *********************************************************************
+ * idecommon_open(ctx)
+ *
+ * Process the CFE OPEN call for this device. For IDE disks,
+ * the device is reset and identified, and the geometry is
+ * determined.
+ *
+ * Input parameters:
+ * ctx - device context
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+
+int idecommon_open(cfe_devctx_t *ctx)
+{
+ idecommon_t *softc = ctx->dev_softc;
+ int res;
+
+ if (softc->idecommon_deferprobe) {
+ res = idecommon_devprobe(softc,0);
+ if (res < 0) return res;
+ }
+
+ return 0;
+}
+
+/* *********************************************************************
+ * idecommon_read(ctx,buffer)
+ *
+ * Process a CFE READ command for the IDE device. This is
+ * more complex than it looks, since CFE offsets are byte offsets
+ * and we may need to read partial sectors.
+ *
+ * Input parameters:
+ * ctx - device context
+ * buffer - buffer descriptor
+ *
+ * Return value:
+ * number of bytes read, or <0 if an error occured
+ ********************************************************************* */
+
+int idecommon_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ idecommon_t *softc = ctx->dev_softc;
+ unsigned char *bptr;
+ int blen;
+ int numsec;
+ int res = 0;
+ int amtcopy;
+ uint64_t lba;
+ uint64_t offset;
+ unsigned char sector[MAX_SECTORSIZE];
+ int sectorshift;
+
+ sectorshift = idecommon_sectorshift(softc->idecommon_sectorsize);
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+ offset = buffer->buf_offset;
+ numsec = (blen + softc->idecommon_sectorsize - 1) >> sectorshift;
+
+ if (offset & (softc->idecommon_sectorsize-1)) {
+ lba = (offset >> sectorshift);
+ res = (*softc->idecommon_readfunc)(softc,lba,1,sector);
+ if (res < 0) goto out;
+ amtcopy = softc->idecommon_sectorsize - (offset & (softc->idecommon_sectorsize-1));
+ if (amtcopy > blen) amtcopy = blen;
+ memcpy(bptr,&sector[offset & (softc->idecommon_sectorsize-1)],amtcopy);
+ bptr += amtcopy;
+ offset += amtcopy;
+ blen -= amtcopy;
+ }
+
+ while (blen >= softc->idecommon_sectorsize) {
+ lba = (offset >> sectorshift);
+ amtcopy = softc->idecommon_sectorsize;
+ res = (*softc->idecommon_readfunc)(softc,lba,1,bptr);
+ if (res < 0) goto out;
+ bptr += amtcopy;
+ offset += amtcopy;
+ blen -= amtcopy;
+ }
+
+ if (blen) {
+ lba = (offset >> sectorshift);
+ res = (*softc->idecommon_readfunc)(softc,lba,1,sector);
+ if (res < 0) goto out;
+ amtcopy = blen;
+ memcpy(bptr,sector,amtcopy);
+ bptr += amtcopy;
+ offset += amtcopy;
+ blen -= amtcopy;
+ }
+
+out:
+ buffer->buf_retlen = bptr - buffer->buf_ptr;
+
+ return res;
+}
+
+/* *********************************************************************
+ * idecommon_inpstat(ctx,inpstat)
+ *
+ * Test input status for the IDE disk. Disks are always ready
+ * to read.
+ *
+ * Input parameters:
+ * ctx - device context
+ * inpstat - input status structure
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+int idecommon_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
+{
+ /* idecommon_t *softc = ctx->dev_softc; */
+
+ inpstat->inp_status = 1;
+ return 0;
+}
+
+/* *********************************************************************
+ * idecommon_write(ctx,buffer)
+ *
+ * Process a CFE WRITE command for the IDE device. If the write
+ * involves partial sectors, the affected sectors are read first
+ * and the changes are merged in.
+ *
+ * Input parameters:
+ * ctx - device context
+ * buffer - buffer descriptor
+ *
+ * Return value:
+ * number of bytes write, or <0 if an error occured
+ ********************************************************************* */
+
+int idecommon_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ idecommon_t *softc = ctx->dev_softc;
+ unsigned char *bptr;
+ int blen;
+ int numsec;
+ int res = 0;
+ int amtcopy;
+ uint64_t offset;
+ uint64_t lba;
+ unsigned char sector[MAX_SECTORSIZE];
+ int sectorshift;
+
+ sectorshift = (softc->idecommon_sectorsize == 2048) ? 11 : 9;
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+ offset = buffer->buf_offset;
+ numsec = (blen + softc->idecommon_sectorsize - 1) >> sectorshift;
+
+ if (offset & (softc->idecommon_sectorsize-1)) {
+ lba = (offset >> sectorshift);
+ res = (*softc->idecommon_readfunc)(softc,lba,1,sector);
+ if (res < 0) goto out;
+ amtcopy = softc->idecommon_sectorsize - (offset & (softc->idecommon_sectorsize-1));
+ if (amtcopy > blen) amtcopy = blen;
+ memcpy(&sector[offset & (softc->idecommon_sectorsize-1)],bptr,amtcopy);
+ res = (*softc->idecommon_writefunc)(softc,lba,1,sector);
+ if (res < 0) goto out;
+ bptr += amtcopy;
+ offset += amtcopy;
+ blen -= amtcopy;
+ }
+
+ while (blen >= softc->idecommon_sectorsize) {
+ amtcopy = softc->idecommon_sectorsize;
+ lba = (offset >> sectorshift);
+ res = (*softc->idecommon_writefunc)(softc,lba,1,bptr);
+ if (res < 0) goto out;
+ bptr += amtcopy;
+ offset += amtcopy;
+ blen -= amtcopy;
+ }
+
+ if (blen) {
+ lba = (offset >> sectorshift);
+ res = (*softc->idecommon_readfunc)(softc,lba,1,sector);
+ if (res < 0) goto out;
+ amtcopy = blen;
+ memcpy(sector,bptr,amtcopy);
+ res = (*softc->idecommon_writefunc)(softc,lba,1,sector);
+ if (res < 0) goto out;
+ bptr += amtcopy;
+ offset += amtcopy;
+ blen -= amtcopy;
+ }
+
+out:
+ buffer->buf_retlen = bptr - buffer->buf_ptr;
+
+ return res;
+}
+
+
+/* *********************************************************************
+ * idecommon_ioctl(ctx,buffer)
+ *
+ * Process device I/O control requests for the IDE device.
+ *
+ * Input parameters:
+ * ctx - device context
+ * buffer - buffer descriptor
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int idecommon_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ idecommon_t *softc = ctx->dev_softc;
+ unsigned int *info = (unsigned int *) buffer->buf_ptr;
+ unsigned long long *linfo = (unsigned long long *) buffer->buf_ptr;
+ blockdev_info_t *devinfo;
+
+ switch ((int)buffer->buf_ioctlcmd) {
+ case IOCTL_BLOCK_GETBLOCKSIZE:
+ *info = softc->idecommon_sectorsize;
+ break;
+ case IOCTL_BLOCK_GETTOTALBLOCKS:
+ *linfo = softc->idecommon_ttlsect;
+ break;
+ case IOCTL_BLOCK_GETDEVTYPE:
+ devinfo = (blockdev_info_t *) buffer->buf_ptr;
+ devinfo->blkdev_totalblocks = softc->idecommon_ttlsect;
+ devinfo->blkdev_blocksize = softc->idecommon_sectorsize;
+ devinfo->blkdev_devtype = (softc->idecommon_devtype == IDE_DEVTYPE_CDROM) ?
+ BLOCK_DEVTYPE_CDROM : BLOCK_DEVTYPE_DISK;
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+/* *********************************************************************
+ * idecommon_close(ctx)
+ *
+ * Close the I/O device.
+ *
+ * Input parameters:
+ * ctx - device context
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+int idecommon_close(cfe_devctx_t *ctx)
+{
+ /* idecommon_t *softc = ctx->dev_softc; */
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * idecommon_init(ide,devtype)
+ *
+ * Set up internal values based on the device type
+ *
+ * Input parameters:
+ * ide - IDE interface
+ * devtype - device type
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void idecommon_init(idecommon_t *ide,int devtype)
+{
+
+ ide->idecommon_devtype = devtype;
+
+ switch (ide->idecommon_devtype) {
+ case IDE_DEVTYPE_DISK:
+ ide->idecommon_atapi = FALSE;
+ ide->idecommon_sectorsize = DISK_SECTORSIZE;
+ break;
+ case IDE_DEVTYPE_CDROM:
+ ide->idecommon_atapi = TRUE;
+ ide->idecommon_sectorsize = CDROM_SECTORSIZE;
+ break;
+ case IDE_DEVTYPE_ATAPIDISK:
+ ide->idecommon_atapi = TRUE;
+ ide->idecommon_sectorsize = DISK_SECTORSIZE;
+ break;
+ default:
+ ide->idecommon_atapi = FALSE;
+ ide->idecommon_sectorsize = DISK_SECTORSIZE;
+ break;
+ }
+
+ if (ide->idecommon_atapi) {
+ ide->idecommon_readfunc = idecommon_read_atapi;
+ ide->idecommon_writefunc = idecommon_write_atapi;
+ }
+ else {
+ ide->idecommon_readfunc = idecommon_read_lba;
+ ide->idecommon_writefunc = idecommon_write_lba;
+ }
+}
+
+/* *********************************************************************
+ * idecommon_attach(devdisp)
+ *
+ * Set up a cfe_devdisp structure that points at the idecommon
+ * structures.
+ *
+ * Input parameters:
+ * devdisp - cfe_devdisp_t structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+void idecommon_attach(cfe_devdisp_t *disp)
+{
+ disp->dev_open = idecommon_open;
+ disp->dev_read = idecommon_read;
+ disp->dev_inpstat = idecommon_inpstat;
+ disp->dev_write = idecommon_write;
+ disp->dev_ioctl = idecommon_ioctl;
+ disp->dev_close = idecommon_close;
+ disp->dev_poll = NULL;
+ disp->dev_reset = NULL;
+}
diff --git a/cfe/cfe/dev/dev_ide_pci.c b/cfe/cfe/dev/dev_ide_pci.c
new file mode 100644
index 0000000..ecf4c2a
--- /dev/null
+++ b/cfe/cfe/dev/dev_ide_pci.c
@@ -0,0 +1,358 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * PCI IDE disk driver File: dev_ide_pci.c
+ *
+ * This is a simple driver for IDE hard disks that are connected
+ * to PCI IDE controllers, such as a Promise UltraXX.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "cfe_timer.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+
+#include "dev_ide_common.h"
+
+#include "dev_ide.h"
+
+#include "pcivar.h"
+#include "pcireg.h"
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define _BYTESWAP_ /* don't byteswap these disks */
+
+#define OUTB(x,y) outb(x,y)
+#define OUTW(x,y) outw(x,y)
+#define INB(x) inb(x)
+#define INW(x) inw(x)
+
+/* *********************************************************************
+ * Forward declarations
+ ********************************************************************* */
+
+extern void _wbflush(void);
+
+static void idedrv_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+/* *********************************************************************
+ * Device Dispatch
+ ********************************************************************* */
+
+static cfe_devdisp_t idedrv_dispatch = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+const cfe_driver_t pciidedrv = {
+ "PCI IDE disk",
+ "ide",
+ CFE_DEV_DISK,
+ &idedrv_dispatch,
+ idedrv_probe
+};
+
+const cfe_driver_t pciatapidrv = {
+ "PCI ATAPI device",
+ "atapi",
+ CFE_DEV_DISK,
+ &idedrv_dispatch,
+ idedrv_probe
+};
+
+/* *********************************************************************
+ * Supported PCI devices
+ ********************************************************************* */
+
+#define DEVID(vid,pid) (((pid)<<16)|(vid))
+
+static uint32_t pciidedrv_devlist[] = {
+ DEVID(0x105a,0x4d33), /* Promise Ultra33 */
+ DEVID(0x1095,0x0649), /* CMD PCI0649 */
+ DEVID(0x1095,0x0648), /* CMD PCI0648 */
+ 0xFFFFFFFF
+};
+
+
+/* *********************************************************************
+ * Port I/O routines
+ *
+ * These routines are called back from the common code to do
+ * I/O cycles to the IDE disk. We provide routines for
+ * reading and writing bytes, words, and strings of words.
+ ********************************************************************* */
+
+static uint8_t idedrv_inb(idecommon_dispatch_t *disp,uint32_t reg)
+{
+ return INB(reg+disp->baseaddr);
+}
+
+static uint16_t idedrv_inw(idecommon_dispatch_t *disp,uint32_t reg)
+{
+ return INW(reg+disp->baseaddr);
+}
+
+static void idedrv_ins(idecommon_dispatch_t *disp,uint32_t reg,uint8_t *buf,int len)
+{
+ uint16_t data;
+
+ while (len > 0) {
+ data = INW(reg+disp->baseaddr);
+
+#ifdef _BYTESWAP_
+ *buf++ = (data >> 8) & 0xFF;
+ *buf++ = (data & 0xFF);
+#else
+ *buf++ = (data & 0xFF);
+ *buf++ = (data >> 8) & 0xFF;
+#endif
+ len--;
+ len--;
+ }
+
+}
+
+static void idedrv_outb(idecommon_dispatch_t *disp,uint32_t reg,uint8_t val)
+{
+ OUTB(reg+disp->baseaddr,val);
+}
+
+static void idedrv_outw(idecommon_dispatch_t *disp,uint32_t reg,uint16_t val)
+{
+ OUTW(reg+disp->baseaddr,val);
+}
+
+static void idedrv_outs(idecommon_dispatch_t *disp,uint32_t reg,uint8_t *buf,int len)
+{
+ uint16_t data;
+
+ while (len > 0) {
+#ifdef _BYTESWAP_
+ data = (uint16_t) buf[1] + ((uint16_t) buf[0] << 8);
+#else
+ data = (uint16_t) buf[0] + ((uint16_t) buf[1] << 8);
+#endif
+
+ OUTW(reg+disp->baseaddr,data);
+
+ buf++;
+ buf++;
+ len--;
+ len--;
+ }
+}
+
+
+/* *********************************************************************
+ * pciidedrv_find(devid,list)
+ *
+ * Find a particular product ID on the list. Return >= 0 if
+ * the ID is valid.
+ *
+ * Input parameters:
+ * devid - product and device ID we have
+ * list - list of product and device IDs we're looking for
+ *
+ * Return value:
+ * index into table, or -1 if not found
+ ********************************************************************* */
+static int pciidedrv_find(uint32_t devid,uint32_t *list)
+{
+ int idx = 0;
+
+ while (list[idx] != 0xFFFFFFFF) {
+ if (list[idx] == devid) return idx;
+ idx++;
+ }
+
+ return -1;
+}
+
+
+/* *********************************************************************
+ * idedrv_probe(drv,probe_a,probe_b,probe_ptr)
+ *
+ * Our probe routine. Attach an IDE device to the firmware.
+ *
+ * Input parameters:
+ * drv - driver structure
+ * probe_a - physical address of IDE registers
+ * probe_b - unit number
+ * probe_ptr - not used
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void idedrv_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ idecommon_t *softc;
+ idecommon_dispatch_t *disp;
+ char descr[80];
+ char unitstr[50];
+ pcitag_t tag;
+ int index;
+ uint32_t devid;
+ uint32_t reg;
+ int res;
+ int unit;
+ cfe_driver_t *realdrv;
+ int attached = 0;
+
+ /*
+ * probe_a is unused
+ * probe_b is unused
+ * probe_ptr is unused.
+ */
+
+ index = 0;
+
+ for (;;) {
+ if (pci_find_class(PCI_CLASS_MASS_STORAGE,index,&tag) != 0) break;
+ index++;
+ devid = pci_conf_read(tag,PCI_ID_REG);
+
+ if (pciidedrv_find(devid,pciidedrv_devlist) < 0) {
+ continue;
+ }
+
+
+ reg = pci_conf_read(tag,PCI_MAPREG(0));
+
+ if (PCI_MAPREG_TYPE(reg) != PCI_MAPREG_TYPE_IO) {
+ xprintf("Skipping this IDE device, we don't do memory mapped IDE yet\n");
+ continue;
+ }
+
+ reg &= ~PCI_MAPREG_TYPE_MASK;
+
+ for (unit = 0; unit < 2; unit++) {
+
+ /*
+ * If we've deliberately disabled probing of this
+ * device, then skip it.
+ */
+
+ if (IDE_PROBE_GET_TYPE(probe_b,unit) == IDE_DEVTYPE_NOPROBE) {
+ continue;
+ }
+
+ softc = (idecommon_t *) KMALLOC(sizeof(idecommon_t),0);
+ disp = (idecommon_dispatch_t *) KMALLOC(sizeof(idecommon_dispatch_t),0);
+
+ if (!softc || !disp) {
+ if (softc) KFREE(softc);
+ if (disp) KFREE(disp);
+ return; /* out of memory, stop here */
+ }
+
+
+ softc->idecommon_addr = reg;
+ disp->ref = softc;
+ disp->baseaddr = softc->idecommon_addr;
+ softc->idecommon_deferprobe = 0;
+ softc->idecommon_dispatch = disp;
+ softc->idecommon_unit = unit;
+
+ disp->outb = idedrv_outb;
+ disp->outw = idedrv_outw;
+ disp->outs = idedrv_outs;
+
+ disp->inb = idedrv_inb;
+ disp->inw = idedrv_inw;
+ disp->ins = idedrv_ins;
+
+ /*
+ * If we're autoprobing, do it now. Loop back if we have
+ * trouble finding the device.
+ *
+ * If not autoprobing, assume the device is there and set the
+ * common routines to double check later.
+ */
+
+ if (IDE_PROBE_GET_TYPE(probe_b,unit) == IDE_DEVTYPE_AUTO) {
+ res = idecommon_devprobe(softc,1);
+ if (res < 0) {
+ KFREE(softc);
+ KFREE(disp);
+ continue;
+ }
+ }
+ else {
+ idecommon_init(softc,IDE_PROBE_GET_TYPE(probe_b,unit));
+ softc->idecommon_deferprobe = 1;
+ }
+
+ xsprintf(descr,"%s unit %d at I/O %04X",drv->drv_description,
+ softc->idecommon_unit,softc->idecommon_addr);
+ xsprintf(unitstr,"%d",unit);
+
+ realdrv = (cfe_driver_t *) (softc->idecommon_atapi ? &pciatapidrv : &pciidedrv);
+
+ idecommon_attach(&idedrv_dispatch);
+ cfe_attach(realdrv,softc,unitstr,descr);
+ attached++;
+ }
+
+ }
+
+ xprintf("PCIIDE: %d controllers found\n",attached);
+}
+
+
diff --git a/cfe/cfe/dev/dev_newflash.c b/cfe/cfe/dev/dev_newflash.c
new file mode 100644
index 0000000..d196e92
--- /dev/null
+++ b/cfe/cfe/dev/dev_newflash.c
@@ -0,0 +1,1428 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * "New" Flash device driver File: dev_newflash.c
+ *
+ * This driver supports various types of flash
+ * parts.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "addrspace.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+#include "cfe_error.h"
+
+#include "bsp_config.h"
+#include "dev_newflash.h"
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define GETCFIBYTE(arr,x) (arr[(x)*2])
+
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#define max(a,b) ((a) > (b) ? (a) : (b))
+
+/*
+ * Get the address of the flash sector buffer from the
+ * config file. Addresses are PHYSICAL.
+ */
+
+#ifndef CFG_FLASH_SECTOR_BUFFER_ADDR
+#define CFG_FLASH_SECTOR_BUFFER_ADDR (100*1024*1024-128*1024)
+#endif
+
+#ifndef CFG_FLASH_SECTOR_BUFFER_SIZE
+#define CFG_FLASH_SECTOR_BUFFER_SIZE (128*1024)
+#endif
+
+
+/*#define _NEWFLASH_DEBUG_ */
+
+/* *********************************************************************
+ * Forward declarations
+ ********************************************************************* */
+
+
+static void flashdrv_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+
+static int flashdrv_open(cfe_devctx_t *ctx);
+static int flashdrv_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int flashdrv_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int flashdrv_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int flashdrv_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int flashdrv_close(cfe_devctx_t *ctx);
+
+/* *********************************************************************
+ * Device dispatch
+ ********************************************************************* */
+
+const static cfe_devdisp_t flashdrv_dispatch = {
+ flashdrv_open,
+ flashdrv_read,
+ flashdrv_inpstat,
+ flashdrv_write,
+ flashdrv_ioctl,
+ flashdrv_close,
+ NULL,
+ NULL
+};
+
+const cfe_driver_t newflashdrv = {
+ "New CFI flash",
+ "flash",
+ CFE_DEV_FLASH,
+ &flashdrv_dispatch,
+ flashdrv_probe
+};
+
+
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+extern void *flashop_engine_ptr;
+extern int flashop_engine_len;
+
+extern void _cfe_flushcache(int);
+
+static int flash_sector_query(flashdev_t *softc,flash_sector_t *sector);
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+/*
+ * This is a pointer to a DRAM version of our flash subroutines.
+ * We make a global here so that it doesn't get copied multiple
+ * times for each flash we instantiate.
+ */
+
+static int (*flashop_engine_ram)(flashinstr_t *prog) = NULL;
+static uint8_t *flash_sector_buffer = NULL;
+
+/* *********************************************************************
+ * FLASH_OP_BEGIN(softc)
+ *
+ * Reset the pointer to the flash operations so that we can
+ * begin filling in new instructions to execute
+ *
+ * Input parameters:
+ * softc - our softc.
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+#define flash_op_begin(softc) softc->fd_iptr = 0;
+
+/* *********************************************************************
+ * FLASH_OP_ADD(softc,op,dest,src,cnt)
+ *
+ * Add an instruction to the flashop table
+ *
+ * Input parameters:
+ * softc - our flash
+ * op,dest,src,cnt - data for the opcode
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void flash_op_add(flashdev_t *softc,long base,long op,long dest,long src,long cnt)
+{
+ flashinstr_t *fi = &(softc->fd_inst[softc->fd_iptr]);
+
+ fi->fi_op = op;
+ fi->fi_base = base;
+ fi->fi_dest = dest;
+ fi->fi_src = src;
+ fi->fi_cnt = cnt;
+
+ softc->fd_iptr++;
+}
+
+
+/* *********************************************************************
+ * FLASH_OP_EXECUTE(softc)
+ *
+ * Execute the stored "flash operations"
+ *
+ * Input parameters:
+ * softc - our flash
+ *
+ * Return value:
+ * 0 if ok, else # of failures (less than zero)
+ ********************************************************************* */
+
+static int flash_op_execute(flashdev_t *softc)
+{
+ flash_op_add(softc,softc->fd_probe.flash_phys,FEOP_RETURN,0,0,0);
+
+#ifdef _NEWFLASH_DEBUG_
+ if (1) {
+ int idx;
+ printf("---------------\nCalling engine @ %08X\n",flashop_engine_ram);
+ for (idx = 0; idx < softc->fd_iptr; idx++) {
+ printf("%2d %08X %08X %08X %08X\n",
+ softc->fd_inst[idx].fi_op,
+ softc->fd_inst[idx].fi_base,
+ softc->fd_inst[idx].fi_dest,
+ softc->fd_inst[idx].fi_src,
+ softc->fd_inst[idx].fi_cnt);
+ }
+ }
+#endif
+
+ /*
+ * If someone hooked the flashop engine, call the hook.
+ */
+ if (softc->fd_probe.flash_engine_hook) {
+ return (*(softc->fd_probe.flash_engine_hook))(&(softc->fd_inst[0]));
+ }
+
+ /*
+ * Otherwise, call the standard one.
+ */
+ if (!flashop_engine_ram) return CFE_ERR_UNSUPPORTED;
+ return (*flashop_engine_ram)(&(softc->fd_inst[0]));
+}
+
+
+/* *********************************************************************
+ * FLASH_SETUP_ENGINE()
+ *
+ * Set up the "flash engine", copying the routine to DRAM
+ * and flushing the cache so we can call it.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void flash_setup_engine(void)
+{
+#if ((CFG_RAMAPP) || (CFG_EMBEDDED_PIC))
+ /* CFE is relocated, no need to copy flash engine to heap */
+ flashop_engine_ram = (void *) flashop_engine_ptr;
+#else
+ /* Copy flash engine to heap */
+ uint32_t *dst,*src;
+ int idx;
+
+ if (flashop_engine_ram) return; /* already done */
+
+ /*
+ * Allocate space for engine
+ */
+
+ flashop_engine_ram = (void *) KMALLOC(flashop_engine_len,0);
+ if (!flashop_engine_ram) return;
+
+ /*
+ * Copy engine to RAM - do it 32-bits at a time to avoid
+ * a certain platform with broken byte reads (no, not the 1250)
+ */
+
+ dst = (uint32_t *) flashop_engine_ram;
+ src = (uint32_t *) flashop_engine_ptr;
+ for (idx = 0; idx < flashop_engine_len/sizeof(uint32_t); idx++) {
+ *dst++ = *src++;
+ }
+
+ /*
+ * Flush the d-cache, invalidate the I-cache.
+ */
+
+ _cfe_flushcache(1);
+ _cfe_flushcache(2);
+#endif
+}
+
+/* *********************************************************************
+ * FLASH_ERASE_RANGE(softc,range)
+ *
+ * Erase a range of sectors
+ *
+ * Input parameters:
+ * softc - our flash
+ * range - range structure
+ *
+ * Return value:
+ * 0 if ok
+ * else error
+ ********************************************************************* */
+
+static int flash_erase_range(flashdev_t *softc,flash_range_t *range)
+{
+ flash_sector_t sector;
+ int res;
+
+ if (softc->fd_probe.flash_type != FLASH_TYPE_FLASH) {
+ return CFE_ERR_UNSUPPORTED;
+ }
+
+ if (range->range_base+range->range_length > softc->fd_probe.flash_size) {
+ return CFE_ERR_INV_PARAM;
+ }
+
+ res = 0;
+
+ sector.flash_sector_idx = 0;
+
+ for (;;) {
+ res = flash_sector_query(softc,&sector);
+ if (res != 0) break;
+ if (sector.flash_sector_status == FLASH_SECTOR_INVALID) {
+ break;
+ }
+
+ if ((sector.flash_sector_offset >= range->range_base) &&
+ (sector.flash_sector_offset <
+ (range->range_base+range->range_length-1))) {
+
+ flash_op_begin(softc);
+ flash_op_add(softc,softc->fd_probe.flash_phys,
+ softc->fd_erasefunc,
+ sector.flash_sector_offset,
+ 0,0);
+ res = flash_op_execute(softc);
+
+ if (res != 0) break;
+ }
+ sector.flash_sector_idx++;
+ }
+
+ return res;
+
+}
+
+/* *********************************************************************
+ * FLASH_ERASE_ALL(softc)
+ *
+ * Erase the entire flash device, except the NVRAM area,
+ * sector-by-sector.
+ *
+ * Input parameters:
+ * softc - our flash
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int flash_erase_all(flashdev_t *softc)
+{
+ flash_range_t range;
+
+ range.range_base = 0;
+ range.range_length = softc->fd_probe.flash_size *
+ softc->fd_probe.flash_nchips;
+
+ return flash_erase_range(softc,&range);
+}
+
+
+/* *********************************************************************
+ * flash_range_intersection(sector,inrange,outrange)
+ *
+ * Compute the intersection between a flash range and a
+ * sector.
+ *
+ * Input parameters:
+ * sector - sector to examine
+ * range - range we are checking
+ * outrange - where to put resulting intersection range
+ *
+ * Return value:
+ * 1 - range is an entire sector
+ * 0 - range is a partial sector
+ * -1 - range has no intersection
+ ********************************************************************* */
+
+static int flash_range_intersection(flash_sector_t *sector,
+ flash_range_t *inrange,
+ flash_range_t *outrange)
+{
+ int start,end;
+
+ /*
+ * compute the start and end pointers
+ */
+
+ start = (int) (max(sector->flash_sector_offset,
+ inrange->range_base));
+
+ end = (int) (min((sector->flash_sector_offset+sector->flash_sector_size),
+ (inrange->range_base+inrange->range_length)));
+
+ /*
+ * if the end is in the right place wrt the start,
+ * there is an intersection.
+ */
+
+ if (end > start) {
+ outrange->range_base = (unsigned int) start;
+ outrange->range_length = (unsigned int) (end-start);
+
+ if ((sector->flash_sector_offset == outrange->range_base) &&
+ (sector->flash_sector_size == outrange->range_length)) {
+ return 1; /* instersection: entire sector */
+ }
+ else {
+ return 0; /* intersection: partial sector */
+ }
+ }
+ else {
+ outrange->range_base = (unsigned int) start;
+ outrange->range_length = 0;
+ return -1; /* intersection: none */
+ }
+}
+
+
+/* *********************************************************************
+ * FLASH_SECTOR_QUERY(softc,sector)
+ *
+ * Query the sector information about a particular sector. You can
+ * call this iteratively to find out about all of the sectors.
+ *
+ * Input parameters:
+ * softc - our flash info
+ * sector - structure to receive sector information
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int flash_sector_query(flashdev_t *softc,flash_sector_t *sector)
+{
+ int idx;
+ int nblks;
+ int blksiz;
+ unsigned int offset;
+ int whichchip;
+ int secidx;
+ int curblk;
+
+ if (softc->fd_probe.flash_type != FLASH_TYPE_FLASH) {
+ return CFE_ERR_UNSUPPORTED;
+ }
+
+ if (softc->fd_probe.flash_nsectors == 0) {
+ return CFE_ERR_UNSUPPORTED;
+ }
+
+ /* Figure out which chip */
+ whichchip = sector->flash_sector_idx / softc->fd_ttlsect;
+ if (whichchip >= softc->fd_probe.flash_nchips) {
+ sector->flash_sector_status = FLASH_SECTOR_INVALID;
+ return 0;
+ }
+
+ /* Within that chip, get sector info */
+ offset = softc->fd_probe.flash_size * whichchip;
+ secidx = sector->flash_sector_idx % softc->fd_ttlsect;
+ curblk = 0;
+
+ for (idx = 0; idx < softc->fd_probe.flash_nsectors; idx++) {
+ nblks = FLASH_SECTOR_NBLKS(softc->fd_probe.flash_sectors[idx]);
+ blksiz = FLASH_SECTOR_SIZE(softc->fd_probe.flash_sectors[idx]);
+ if (secidx < curblk+nblks) {
+ sector->flash_sector_status = FLASH_SECTOR_OK;
+ sector->flash_sector_offset =
+ offset + (secidx-curblk)*blksiz;
+ sector->flash_sector_size = blksiz;
+ break;
+ }
+
+ offset += (nblks)*blksiz;
+ curblk += nblks;
+ }
+
+
+ if (idx == softc->fd_probe.flash_nsectors) {
+ sector->flash_sector_status = FLASH_SECTOR_INVALID;
+ }
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * FLASH_SET_CMDSET(softc,cmdset,bus16,dev16)
+ *
+ * Set the command-set that we'll honor for this flash.
+ *
+ * Input parameters:
+ * softc - our flash
+ * cmdset - FLASH_CFI_CMDSET_xxx
+ * bus16 - true if bus is 16 bits wide
+ * dev16 - true if device supports 16-bit operation
+ *
+ * So: bus16 && dev16 -> 16-bit commands
+ * !bus16 && dev16 -> 8-bit commands to 16-bit flash with BYTE#
+ * !bus16 && !dev16 -> 8-bit commands
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void flash_set_cmdset(flashdev_t *softc,int cmdset,int bus16,int dev16)
+{
+ switch (cmdset) {
+#if (FLASH_DRIVERS & FLASH_DRIVER_INTEL)
+ case FLASH_CFI_CMDSET_INTEL_ECS:
+ case FLASH_CFI_CMDSET_INTEL_STD:
+ if (bus16) {
+ softc->fd_erasefunc = FEOP_INTEL_ERASE16;
+ softc->fd_pgmfunc = FEOP_INTEL_PGM16;
+ softc->fd_readfunc = FEOP_READ16;
+ }
+ else {
+ softc->fd_erasefunc = FEOP_INTEL_ERASE8;
+ softc->fd_pgmfunc = FEOP_INTEL_PGM8;
+ softc->fd_readfunc = FEOP_READ8;
+ }
+ break;
+#endif
+#if (FLASH_DRIVERS & FLASH_DRIVER_AMD)
+ case FLASH_CFI_CMDSET_AMD_STD:
+ case FLASH_CFI_CMDSET_AMD_ECS:
+ if (!bus16 && !dev16) { /* 8-bit bus, 8-bit flash */
+ softc->fd_erasefunc = FEOP_AMD_ERASE8;
+ softc->fd_pgmfunc = FEOP_AMD_PGM8;
+ softc->fd_readfunc = FEOP_READ8;
+ }
+ else if (bus16 && dev16) { /* 16-bit bus, 16-bit flash */
+ softc->fd_erasefunc = FEOP_AMD_ERASE16;
+ softc->fd_pgmfunc = FEOP_AMD_PGM16;
+ softc->fd_readfunc = FEOP_READ16;
+ }
+ else { /* 8-bit bus, 16-bit flash w/BYTE# */
+ softc->fd_erasefunc = FEOP_AMD_ERASE16B;
+ softc->fd_pgmfunc = FEOP_AMD_PGM16B;
+ softc->fd_readfunc = FEOP_READ8;
+ }
+ break;
+#endif
+ default:
+ /* we don't understand the command set - treat it like ROM */
+ softc->fd_erasefunc = FEOP_RETURN;
+ softc->fd_pgmfunc = FEOP_RETURN;
+ softc->fd_readfunc = bus16 ? FEOP_READ16 : FEOP_READ8;
+ break;
+ }
+}
+
+#if (FLASH_DRIVERS & FLASH_DRIVER_CFI)
+/* *********************************************************************
+ * FLASH_CFI_PROBE(softc)
+ *
+ * Try to do a CFI query on this device. If we find the m
+ * magic signature, extract some useful information from the
+ * query structure.
+ *
+ * Input parameters:
+ * softc - out flash
+ *
+ * Return value:
+ * 0 if successful, <0 if error
+ ********************************************************************* */
+static int flash_cfi_probe(flashdev_t *softc)
+{
+ uint8_t cfidata[FLASH_MAX_CFIDATA];
+ unsigned int cmdset;
+ unsigned int devif;
+ int bus16 = 0;
+ int dev16 = 0;
+ int idx;
+ int found = 0;
+ int regcnt;
+ int nblks;
+ int blksiz;
+ int insane = 0;
+ uint8_t insaner = 0;
+
+ if (softc->fd_probe.flash_flags & FLASH_FLG_BUS16) {
+ bus16 = 1;
+ }
+
+ /*
+ * Do a CFI query (16-bit)
+ */
+
+ idx = FEOP_CFIQUERY8;
+ if (softc->fd_probe.flash_flags & FLASH_FLG_DEV16) {
+ idx = (softc->fd_probe.flash_flags & FLASH_FLG_BUS16) ?
+ FEOP_CFIQUERY16 : FEOP_CFIQUERY16B;
+ }
+
+ flash_op_begin(softc);
+ flash_op_add(softc,softc->fd_probe.flash_phys,
+ idx,(long)cfidata,0,FLASH_MAX_CFIDATA);
+ flash_op_execute(softc);
+
+ /*
+ * Look for signature.
+ */
+
+
+ if ((GETCFIBYTE(cfidata,FLASH_CFI_SIGNATURE+0) == 'Q') &&
+ (GETCFIBYTE(cfidata,FLASH_CFI_SIGNATURE+1) == 'R') &&
+ (GETCFIBYTE(cfidata,FLASH_CFI_SIGNATURE+2) == 'Y')) {
+ found = 1;
+ }
+
+
+ /*
+ * No CFI, bail. First, set the command set to an invalid
+ * value so that we'll use default routines to read but not do programming
+ */
+
+ if (!found) {
+ flash_set_cmdset(softc,-1,bus16,dev16);
+ return CFE_ERR_UNSUPPORTED;
+ }
+
+ softc->fd_probe.flash_type = FLASH_TYPE_FLASH;
+
+ /*
+ * Gather info from flash
+ */
+
+ cmdset = ((unsigned int) (GETCFIBYTE(cfidata,FLASH_CFI_COMMAND_SET))) +
+ (((unsigned int) (GETCFIBYTE(cfidata,FLASH_CFI_COMMAND_SET+1))) << 8);
+
+
+ devif = ((unsigned int) (GETCFIBYTE(cfidata,FLASH_CFI_DEVICE_INTERFACE))) +
+ (((unsigned int) (GETCFIBYTE(cfidata,FLASH_CFI_DEVICE_INTERFACE+1))) << 8);
+
+
+ softc->fd_probe.flash_size = (1 << (unsigned int)(GETCFIBYTE(cfidata,FLASH_CFI_DEVICE_SIZE)));
+
+ /*
+ * It's a 16-bit device if it is either always 16 bits or can be.
+ * we'll use "bus16" to decide if the BYTE# pin was strapped
+ */
+
+ dev16 = 0;
+ if ((devif == FLASH_CFI_DEVIF_X16) || (devif == FLASH_CFI_DEVIF_X8X16)) dev16 = 1;
+
+ regcnt = GETCFIBYTE(cfidata,FLASH_CFI_REGION_COUNT);
+
+ softc->fd_probe.flash_nsectors = regcnt;
+
+#if 1
+ /*
+ * Hiss! Some AMD top-boot flash parts have broken CFI tables - they are backwards!
+ * Do some extra probing to find it.
+ */
+
+ if (cmdset == FLASH_CFI_CMDSET_AMD_STD) {
+ idx = FEOP_AMD_DEVCODE8;
+ if (softc->fd_probe.flash_flags & FLASH_FLG_DEV16) {
+ idx = (softc->fd_probe.flash_flags & FLASH_FLG_BUS16) ?
+ FEOP_AMD_DEVCODE16 : FEOP_AMD_DEVCODE16B;
+ }
+
+ flash_op_begin(softc);
+ flash_op_add(softc,softc->fd_probe.flash_phys,
+ idx,(long)&insaner,0,0);
+ flash_op_execute(softc);
+#ifdef _NEWFLASH_DEBUG_
+ xprintf("Insaner = 0x%x\n", insaner);
+#endif /* _NEWFLASH_DEBUG_ */
+ if(((insaner & 0xFF) == 0xC4)||((insaner & 0xFF) == 0xF6)){
+ insane = 1;
+#ifdef _NEWFLASH_DEBUG_
+ xprintf("Warning: insane AMD part, backwards CFI table!\n");
+#endif /* _NEWFLASH_DEBUG_ */
+ }
+ }
+#else
+ insane = insaner = 1;
+#endif /* 0 */
+
+
+ for (idx = 0; idx < regcnt; idx++) {
+ nblks = ((int)GETCFIBYTE(cfidata,FLASH_CFI_REGION_TABLE+0+idx*4) +
+ (int)(GETCFIBYTE(cfidata,FLASH_CFI_REGION_TABLE+1+idx*4)<<8)) + 1;
+ blksiz = ((int)GETCFIBYTE(cfidata,FLASH_CFI_REGION_TABLE+2+idx*4) +
+ (int)(GETCFIBYTE(cfidata,FLASH_CFI_REGION_TABLE+3+idx*4)<<8)) * 256;
+
+ if (insane) {
+ /* Insane */
+ softc->fd_probe.flash_sectors[((regcnt-1)-idx)] =
+ FLASH_SECTOR_RANGE(nblks,blksiz);
+ }
+ else {
+ /* Sane */
+ softc->fd_probe.flash_sectors[idx] =
+ FLASH_SECTOR_RANGE(nblks,blksiz);
+ }
+ }
+
+ /*
+ * Set the command set we're going to use.
+ */
+
+ flash_set_cmdset(softc,cmdset,bus16,dev16);
+
+ return 0;
+
+}
+
+
+
+/* *********************************************************************
+ * FLASH_DO_PROBE(softc)
+ *
+ * Probe to see if we're ROM or RAM. If ROM, see if we're flash.
+ * If flash, do CFI query.
+ *
+ * Input parameters:
+ * softc - our structure
+ *
+ * Return value:
+ * FLASH_TYPE_xxx
+ ********************************************************************* */
+static int flash_do_probe(flashdev_t *softc)
+{
+ uint8_t test_byte0,test_byte1;
+ uint8_t save0,save1;
+ volatile uint8_t *ptr;
+
+ /*
+ * flash_do_probe is called before we open the device, so we
+ * need to allocate space for instructions so the flashop
+ * engine will work.
+ */
+
+ softc->fd_inst = KMALLOC(FLASH_MAX_INST*sizeof(flashinstr_t),0);
+ if (!softc->fd_inst) return FLASH_TYPE_ROM;
+
+ /*
+ * Attempt to read/write byte zero. If it is changable,
+ * this is SRAM (or maybe a ROM emulator with the write line hooked up)
+ */
+
+ ptr = (volatile uint8_t *) UNCADDR(softc->fd_probe.flash_phys);
+ save0 = *ptr; /* save old value */
+ save1 = *(ptr+1); /* save old value */
+
+ test_byte0 = (save0 != 0x88) ? 0x88 : 0x89;
+ test_byte1 = (save1 != 0x99) ? 0x99 : 0x91;
+
+ *(ptr) = test_byte0;
+ *(ptr+1) = test_byte1;
+
+ if ((*ptr == test_byte0) && (*(ptr+1) == test_byte1)) {
+ softc->fd_probe.flash_type = FLASH_TYPE_SRAM;
+
+ /*Only write back saved values if it's RAM*/
+ *(ptr) = save0;
+ *(ptr+1) = save1;
+
+#ifdef _NEWFLASH_DEBUG_
+ xprintf("Flash type SRAM\n");
+#endif
+
+ }
+ else {
+ softc->fd_probe.flash_type = FLASH_TYPE_ROM;
+
+#ifdef _NEWFLASH_DEBUG_
+ xprintf("Flash type ROM\n");
+#endif
+
+ }
+
+ /*
+ * If we thought it was ROM, try doing a CFI query
+ * to see if it was flash. This check is kind of kludgey
+ * but should work.
+ */
+
+ if (softc->fd_probe.flash_type == FLASH_TYPE_ROM) {
+ flash_cfi_probe(softc);
+ }
+
+
+ KFREE(softc->fd_inst);
+ softc->fd_inst = NULL;
+
+ return softc->fd_probe.flash_type;
+}
+
+#endif /* (FLASH_DRIVERS & FLASH_DRIVER_CFI) */
+
+
+/* *********************************************************************
+ * flash_do_parts(probe,parts)
+ *
+ * Partition the flash into the sizes specified. We use
+ * the sizes in the table to generate a table of {offset,size}
+ * pairs that eventually become partitions.
+ *
+ * The only thing magical about this is that size "0" means
+ * "fill to max" and that partitions beyond the "0" are aligned
+ * to the top of the flash. Therefore, if you had a 4MB
+ * flash and listed four partitions, 512K, 0, 512K, 512K,
+ * then there would be a 2.5M partition in the middle and two
+ * 512K partitions at the top.
+ *
+ * Input parameters:
+ * probe - flash probe data (user-supplied table)
+ * parts - our partition table (output)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void flash_do_parts(flashdev_t *softc)
+{
+ int idx;
+ int middlepart = -1;
+ int lobound = 0;
+ newflash_probe_t *probe = &(softc->fd_probe);
+ flashpart_t *parts = &(softc->fd_parts[0]);
+ int hibound = probe->flash_size*probe->flash_nchips;
+
+ for (idx = 0; idx < probe->flash_nparts; idx++) {
+ if (probe->flash_parts[idx].fp_size == 0) {
+ middlepart = idx;
+ break;
+ }
+ parts[idx].fp_offset = lobound;
+ parts[idx].fp_size = probe->flash_parts[idx].fp_size;
+ lobound += probe->flash_parts[idx].fp_size;
+ }
+
+ if (idx != probe->flash_nparts) {
+ for (idx = probe->flash_nparts - 1; idx > middlepart;
+ idx--) {
+ parts[idx].fp_size = probe->flash_parts[idx].fp_size;
+ hibound -= probe->flash_parts[idx].fp_size;
+ parts[idx].fp_offset = hibound;
+ }
+ }
+
+ if (middlepart != -1) {
+ parts[middlepart].fp_offset = lobound;
+ parts[middlepart].fp_size = hibound - lobound;
+ }
+
+#ifdef _NEWFLASH_DEBUG_
+ printf("Partition information:\n");
+ for (idx = 0; idx < probe->flash_nparts;idx++) {
+ printf("#%02d %08X -> %08X (%d)\n",idx,
+ parts[idx].fp_offset,parts[idx].fp_offset+parts[idx].fp_size-1,
+ parts[idx].fp_size);
+ }
+#endif
+}
+
+
+/* *********************************************************************
+ * flashdrv_allocbuf(dev)
+ *
+ * Allocate sector buffer for flash programming. Use a global
+ * buffer for all devices.
+ *
+ * Input parameters:
+ * dev - our device
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void flashdrv_allocbuf(flashdev_t *softc)
+{
+ if (!flash_sector_buffer) {
+#if CFG_FLASH_ALLOC_SECTOR_BUFFER
+ flash_sector_buffer = KMALLOC(CFG_FLASH_SECTOR_BUFFER_SIZE,0);
+ if (!flash_sector_buffer) {
+ printf("FLASH: Could not allocate sector buffer, using default\n");
+ flash_sector_buffer = (uint8_t *) KERNADDR(CFG_FLASH_SECTOR_BUFFER_SIZE);
+ }
+#else
+ flash_sector_buffer = (uint8_t *) KERNADDR(CFG_FLASH_SECTOR_BUFFER_ADDR);
+#endif
+ }
+
+ softc->fd_sectorbuffer = flash_sector_buffer;
+}
+
+/* *********************************************************************
+ * flashdrv_probe(drv,probe_a,probe_b,probe_ptr)
+ *
+ * Device probe routine. Attach the flash device to
+ * CFE's device table.
+ *
+ * Input parameters:
+ * drv - driver descriptor
+ * probe_a - physical address of flash
+ * probe_b - size of flash (bytes)
+ * probe_ptr - unused
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void flashdrv_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ flashdev_t *softc;
+ newflash_probe_t *probe;
+ int idx;
+ char descr[80];
+ static int flashidx = 0;
+ char *x;
+
+ /*
+ * First thing to do is configure the flashop engine
+ * if not already done. Basically we copy a bit of
+ * position-independent code into the DRAM.
+ */
+
+ flash_setup_engine();
+
+ /*
+ * Now, on with the probing.
+ */
+
+ probe = (newflash_probe_t *) probe_ptr;
+
+ /*
+ * probe_a is the flash base address
+ * probe_b is the size of the flash
+ * probe_ptr is unused.
+ */
+
+ softc = (flashdev_t *) KMALLOC(sizeof(flashdev_t),0);
+ if (softc) {
+ memset(softc,0,sizeof(flashdev_t));
+
+ flashdrv_allocbuf(softc);
+
+ if (probe) {
+ /*
+ * Passed probe structure, do fancy stuff
+ */
+ memcpy(&(softc->fd_probe),probe,sizeof(newflash_probe_t));
+ if (softc->fd_probe.flash_nchips == 0) {
+ softc->fd_probe.flash_nchips = 1;
+ }
+ }
+ else {
+ /* Didn't pass probe structure, do the compatible thing */
+ softc->fd_probe.flash_phys = probe_a;
+ softc->fd_probe.flash_size = (probe_b & FLASH_SIZE_MASK);
+ softc->fd_probe.flash_flags = (probe_b & FLASH_FLG_MASK);
+ softc->fd_probe.flash_nchips = 1;
+ }
+
+ if (softc->fd_probe.flash_flags & FLASH_FLG_MANUAL) {
+ /* Manual probing, just set the command set. */
+ flash_set_cmdset(softc,softc->fd_probe.flash_cmdset,
+ ((softc->fd_probe.flash_flags & FLASH_FLG_BUS16) ? 1 : 0),
+ ((softc->fd_probe.flash_flags & FLASH_FLG_DEV16) ? 1 : 0));
+ }
+ else {
+ /* Do automatic probing */
+#if (FLASH_DRIVERS & FLASH_DRIVER_CFI)
+ flash_do_probe(softc);
+#else
+ return; /* No automatic probing, bail! */
+#endif
+ }
+
+ /* Remember total size of all devices */
+ softc->fd_ttlsize = softc->fd_probe.flash_nchips * softc->fd_probe.flash_size;
+
+ /* Set description */
+ x = descr;
+ x += xsprintf(x,"%s at %08X size %uKB",drv->drv_description,
+ softc->fd_probe.flash_phys,
+ softc->fd_ttlsize/1024);
+ if (softc->fd_probe.flash_nchips > 1) {
+ xsprintf(x," (%d chips)",softc->fd_probe.flash_nchips);
+ }
+
+ /*
+ * If flash is not partitioned, just instantiate one
+ * device. Otherwise, instantiate multiple flashes
+ * to cover the entire device.
+ */
+
+ if (softc->fd_probe.flash_nparts == 0) {
+ softc->fd_parts[0].fp_dev = softc;
+ softc->fd_parts[0].fp_offset = 0;
+ softc->fd_parts[0].fp_size = softc->fd_probe.flash_size;
+ cfe_attach(drv,&(softc->fd_parts[0]),NULL,descr);
+ }
+ else {
+ /*
+ * Partition flash into chunks
+ */
+ flash_do_parts(softc);
+
+ /*
+ * Instantiate devices for each piece
+ */
+
+ for (idx = 0; idx < softc->fd_probe.flash_nparts; idx++) {
+ char name[32];
+ char *nptr;
+
+ xsprintf(descr,"%s at %08X offset %08X size %uKB",
+ drv->drv_description,
+ softc->fd_probe.flash_phys,
+ softc->fd_parts[idx].fp_offset,
+ (softc->fd_parts[idx].fp_size+1023)/1024);
+
+ softc->fd_parts[idx].fp_dev = softc;
+ if (softc->fd_probe.flash_parts[idx].fp_name == NULL) {
+ sprintf(name,"%d",idx);
+ nptr = name;
+ }
+ else {
+ nptr = softc->fd_probe.flash_parts[idx].fp_name;
+ }
+ cfe_attach_idx(drv,
+ flashidx,
+ &(softc->fd_parts[idx]),
+ nptr,
+ descr);
+ }
+ }
+
+ flashidx++;
+
+ /* Count total sectors on the device */
+
+ softc->fd_ttlsect = 0;
+ for (idx = 0; idx < softc->fd_probe.flash_nsectors; idx++) {
+ softc->fd_ttlsect += FLASH_SECTOR_NBLKS(softc->fd_probe.flash_sectors[idx]);
+ }
+
+ }
+
+}
+
+
+/* *********************************************************************
+ * flashdrv_open(ctx)
+ *
+ * Called when the flash device is opened.
+ *
+ * Input parameters:
+ * ctx - device context
+ *
+ * Return value:
+ * 0 if ok else error code
+ ********************************************************************* */
+
+static int flashdrv_open(cfe_devctx_t *ctx)
+{
+ flashpart_t *part = ctx->dev_softc;
+ flashdev_t *softc = part->fp_dev;
+ int ttlsect = softc->fd_ttlsect;
+
+ /*
+ * Calculate number of flashop instructions we'll need at most.
+ * This will be two for each sector plus two more for the first
+ * and last sectors, plus two extra
+ */
+
+ ttlsect = (ttlsect * 2 * softc->fd_probe.flash_nchips) + 6;
+
+ /*
+ * Allocate memory for instructions.
+ */
+
+#ifdef _NEWFLASH_DEBUG_
+ printf("%s: allocating %d instructions\n",cfe_device_name(ctx),ttlsect);
+#endif
+
+ softc->fd_inst = KMALLOC(ttlsect*sizeof(flashinstr_t),0);
+ if (!softc->fd_inst) return CFE_ERR_NOMEM;
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * flashdrv_read(ctx,buffer)
+ *
+ * Read data from the flash device. The flash device is
+ * considered to be like a disk (you need to specify the offset).
+ *
+ * Input parameters:
+ * ctx - device context
+ * buffer - buffer descriptor
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+static int flashdrv_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ flashpart_t *part = ctx->dev_softc;
+ flashdev_t *softc = part->fp_dev;
+ int blen;
+ int offset;
+
+ blen = buffer->buf_length;
+ offset = (long)buffer->buf_offset;
+
+ if ((offset + blen) > part->fp_size) {
+ blen = part->fp_size - offset;
+ }
+
+ offset += part->fp_offset;
+
+ if (blen > 0) {
+ flash_op_begin(softc);
+ flash_op_add(softc,softc->fd_probe.flash_phys,
+ softc->fd_readfunc,(long)buffer->buf_ptr,offset,blen);
+ flash_op_execute(softc);
+ }
+
+ buffer->buf_retlen = blen;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * flashdrv_inpstat(ctx,inpstat)
+ *
+ * Return "input status". For flash devices, we always return true.
+ *
+ * Input parameters:
+ * ctx - device context
+ * inpstat - input status structure
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+static int flashdrv_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
+{
+ inpstat->inp_status = 1;
+ return 0;
+}
+
+
+/* *********************************************************************
+ * flashdrv_write(ctx,buffer)
+ *
+ * Write data to the flash device. The flash device is
+ * considered to be like a disk (you need to specify the offset).
+ *
+ * Input parameters:
+ * ctx - device context
+ * buffer - buffer descriptor
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+static int flashdrv_write2(cfe_devctx_t *ctx,iocb_buffer_t *buffer,int reboot)
+{
+ flashpart_t *part = ctx->dev_softc;
+ flashdev_t *softc = part->fp_dev;
+ int blen;
+ int res;
+ int offset;
+ int whichchip;
+ long chipbase;
+ flash_range_t outrange;
+ flash_range_t inrange;
+ flash_sector_t sector;
+
+ blen = buffer->buf_length;
+ offset = (long)buffer->buf_offset;
+
+ /* Compute range within physical flash */
+
+ if ((offset + blen) > part->fp_size) {
+ blen = part->fp_size - offset;
+ }
+
+ offset += part->fp_offset;
+
+ /* Handle case of writing nothing */
+
+ if (blen == 0) {
+ buffer->buf_retlen = blen;
+ return (buffer->buf_length == blen) ? 0 : CFE_ERR_IOERR;
+ }
+
+ /* now, offset/blen forms the range we want to write to. */
+
+ inrange.range_base = offset;
+ inrange.range_length = blen;
+
+ sector.flash_sector_idx = 0;
+
+ flash_op_begin(softc);
+
+ for (;;) {
+ res = flash_sector_query(softc,&sector);
+ if (res != 0) break;
+ if (sector.flash_sector_status == FLASH_SECTOR_INVALID) {
+ break;
+ }
+
+ whichchip = sector.flash_sector_idx / softc->fd_ttlsect;
+ chipbase = softc->fd_probe.flash_phys +
+ (long) (whichchip * softc->fd_probe.flash_size);
+
+ res = flash_range_intersection(&sector,&inrange,&outrange);
+
+ switch (res) {
+ case 1: /* Erease/program entire sector */
+ flash_op_add(softc,chipbase,
+ softc->fd_erasefunc,
+ sector.flash_sector_offset,
+ 0,0);
+ flash_op_add(softc,chipbase,
+ softc->fd_pgmfunc,
+ outrange.range_base,
+ ((long)buffer->buf_ptr)+(outrange.range_base-inrange.range_base),
+ outrange.range_length);
+ break;
+
+ case 0: /* Erase/reprogram partial sector */
+ /* Save old sector */
+ flash_op_add(softc,chipbase,
+ softc->fd_readfunc,
+ (long)(softc->fd_sectorbuffer),
+ sector.flash_sector_offset,
+ sector.flash_sector_size);
+ /* Copy in new stuff */
+ flash_op_add(softc,chipbase,
+ FEOP_MEMCPY,
+ ((long)(softc->fd_sectorbuffer))+(outrange.range_base-sector.flash_sector_offset),
+ ((long)buffer->buf_ptr)+(outrange.range_base-inrange.range_base),
+ outrange.range_length);
+ /* Erase sector */
+ flash_op_add(softc,chipbase,
+ softc->fd_erasefunc,
+ sector.flash_sector_offset,
+ 0,0);
+ /* Program sector */
+ flash_op_add(softc,chipbase,
+ softc->fd_pgmfunc,
+ sector.flash_sector_offset,
+ (long)(softc->fd_sectorbuffer),
+ sector.flash_sector_size);
+ break;
+
+ case -1: /* No intersection */
+ break;
+ }
+
+ sector.flash_sector_idx++;
+
+ }
+
+ if (reboot) {
+ flash_op_add(softc,softc->fd_probe.flash_phys,FEOP_REBOOT,0,0,0);
+ }
+
+ res = flash_op_execute(softc);
+
+ buffer->buf_retlen = blen;
+
+ return (res == 0) ? 0 : CFE_ERR_IOERR;
+}
+
+static int flashdrv_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ return flashdrv_write2(ctx,buffer,0);
+}
+
+
+/* *********************************************************************
+ * flashdrv_ioctl(ctx,buffer)
+ *
+ * Handle special IOCTL functions for the flash. Flash devices
+ * support NVRAM information, sector and chip erase, and a
+ * special IOCTL for updating the running copy of CFE.
+ *
+ * Input parameters:
+ * ctx - device context
+ * buffer - descriptor for IOCTL parameters
+ *
+ * Return value:
+ * 0 if ok else error
+ ********************************************************************* */
+static int flashdrv_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ flashpart_t *part = ctx->dev_softc;
+ flashdev_t *softc = part->fp_dev;
+ nvram_info_t *nvinfo;
+ flash_info_t *info;
+ flash_range_t range;
+ int offset;
+
+ switch ((int)buffer->buf_ioctlcmd) {
+ case IOCTL_NVRAM_GETINFO:
+ /*
+ * We only support NVRAM on flashes that have been partitioned
+ * into at least two partitions. Every partition supports
+ * being an NVRAM in that case, but we'll only attach one
+ * of them to the environment subsystem.
+ */
+ if (softc->fd_probe.flash_nparts <= 1) {
+ return CFE_ERR_UNSUPPORTED;
+ }
+ nvinfo = (nvram_info_t *) buffer->buf_ptr;
+ if (buffer->buf_length != sizeof(nvram_info_t)) return CFE_ERR_INV_PARAM;
+
+ nvinfo->nvram_offset = 0;
+ nvinfo->nvram_size = part->fp_size;
+ nvinfo->nvram_eraseflg = 1;
+ buffer->buf_retlen = sizeof(nvram_info_t);
+ return 0;
+ break;
+
+ case IOCTL_FLASH_ERASE_SECTOR:
+ offset = (int) buffer->buf_offset;
+ offset += part->fp_offset;
+ if (offset >= softc->fd_probe.flash_size) return -1;
+
+ flash_op_begin(softc);
+ flash_op_add(softc,
+ softc->fd_probe.flash_phys,
+ softc->fd_erasefunc,
+ offset,
+ 0,0);
+ flash_op_execute(softc);
+ return 0;
+
+ case IOCTL_FLASH_ERASE_ALL:
+ offset = (int) buffer->buf_offset;
+ if (offset != 0) return -1;
+ flash_erase_all(softc);
+ return 0;
+
+ case IOCTL_FLASH_WRITE_ALL:
+ /* Write file and reboot */
+ flashdrv_write2(ctx,buffer,1);
+ return -1; /* should not return */
+
+ case IOCTL_FLASH_GETINFO:
+ info = (flash_info_t *) buffer->buf_ptr;
+ info->flash_base = softc->fd_probe.flash_phys;
+ info->flash_size = softc->fd_probe.flash_size;
+ info->flash_type = softc->fd_probe.flash_type;
+ info->flash_flags = FLASH_FLAG_NOERASE;
+ return 0;
+
+ case IOCTL_FLASH_GETSECTORS:
+ return flash_sector_query(softc,(flash_sector_t *) buffer->buf_ptr);
+
+ case IOCTL_FLASH_ERASE_RANGE:
+ memcpy(&range,buffer->buf_ptr,sizeof(flash_range_t));
+ range.range_base += part->fp_offset;
+ if (range.range_length > part->fp_size) {
+ range.range_length = part->fp_size;
+ }
+ return flash_erase_range(softc,&range);
+
+ default:
+ /* Call hook if present. */
+ if (softc->fd_probe.flash_ioctl_hook) {
+ return (*(softc->fd_probe.flash_ioctl_hook))(ctx,buffer);
+ }
+ return -1;
+ }
+
+ return -1;
+}
+
+
+/* *********************************************************************
+ * flashdrv_close(ctx)
+ *
+ * Close the flash device.
+ *
+ * Input parameters:
+ * ctx - device context
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+static int flashdrv_close(cfe_devctx_t *ctx)
+{
+ flashpart_t *part = ctx->dev_softc;
+ flashdev_t *softc = part->fp_dev;
+
+ if (softc->fd_inst) {
+ KFREE(softc->fd_inst);
+ }
+
+ softc->fd_inst = NULL;
+
+ /* XXX Invalidate the cache ?!?! */
+
+ return 0;
+}
+
+
diff --git a/cfe/cfe/dev/dev_ns16550.c b/cfe/cfe/dev/dev_ns16550.c
new file mode 100644
index 0000000..a70eecf
--- /dev/null
+++ b/cfe/cfe/dev/dev_ns16550.c
@@ -0,0 +1,255 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * NS16550 UART driver File: dev_ns16550.c
+ *
+ * This is a console device driver for an NS16550 UART, either
+ * on-board or as a PCI-device. In the case of a PCI device,
+ * our probe routine is called from the PCI probe code
+ * over in dev_ns16550_pci.c
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+
+#include "lib_physio.h"
+
+#include "bsp_config.h"
+
+#include "ns16550.h"
+
+#define WRITECSR(p,v) phys_write8((p),(v))
+#define READCSR(p) phys_read8((p))
+
+static int ns16550_uart_open(cfe_devctx_t *ctx);
+static int ns16550_uart_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int ns16550_uart_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int ns16550_uart_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int ns16550_uart_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int ns16550_uart_close(cfe_devctx_t *ctx);
+
+void ns16550_uart_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+
+const cfe_devdisp_t ns16550_uart_dispatch = {
+ ns16550_uart_open,
+ ns16550_uart_read,
+ ns16550_uart_inpstat,
+ ns16550_uart_write,
+ ns16550_uart_ioctl,
+ ns16550_uart_close,
+ NULL,
+ NULL
+};
+
+const cfe_driver_t ns16550_uart = {
+ "NS16550 UART",
+ "uart",
+ CFE_DEV_SERIAL,
+ &ns16550_uart_dispatch,
+ ns16550_uart_probe
+};
+
+typedef struct ns16550_uart_s {
+ physaddr_t uart_base;
+ int uart_flowcontrol;
+ int uart_speed;
+} ns16550_uart_t;
+
+
+/*
+ * NS16550-compatible UART.
+ * probe_a: physical address of UART
+ */
+
+void ns16550_uart_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ ns16550_uart_t *softc;
+ char descr[80];
+
+ softc = (ns16550_uart_t *) KMALLOC(sizeof(ns16550_uart_t),0);
+ if (softc) {
+ softc->uart_base = probe_a;
+ softc->uart_speed = CFG_SERIAL_BAUD_RATE;
+ softc->uart_flowcontrol = SERIAL_FLOW_NONE;
+ xsprintf(descr, "%s at 0x%X", drv->drv_description, (uint32_t)probe_a);
+
+ cfe_attach(drv, softc, NULL, descr);
+ }
+}
+
+#define DELAY(n) delay(n)
+extern int32_t _getticks(void);
+static void delay(int ticks)
+{
+ int32_t t;
+
+ t = _getticks() + ticks;
+ while (_getticks() < t)
+ ; /* NULL LOOP */
+}
+
+static void ns16550_uart_setflow(ns16550_uart_t *softc)
+{
+ /* noop for now */
+}
+
+
+static int ns16550_uart_open(cfe_devctx_t *ctx)
+{
+ ns16550_uart_t *softc = ctx->dev_softc;
+ int baudrate = CFG_SERIAL_BAUD_RATE;
+ unsigned int brtc;
+
+ brtc = BRTC(baudrate);
+
+ WRITECSR(softc->uart_base+R_UART_CFCR,CFCR_DLAB);
+ WRITECSR(softc->uart_base+R_UART_DATA,brtc & 0xFF);
+ WRITECSR(softc->uart_base+R_UART_IER,brtc>>8);
+ WRITECSR(softc->uart_base+R_UART_CFCR,CFCR_8BITS);
+ WRITECSR(softc->uart_base+R_UART_MCR,MCR_DTR | MCR_RTS | MCR_IENABLE);
+ WRITECSR(softc->uart_base+R_UART_IER,0);
+
+ WRITECSR(softc->uart_base+R_UART_FIFO,FIFO_ENABLE);
+ DELAY(100);
+ WRITECSR(softc->uart_base+R_UART_FIFO,
+ FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1);
+ DELAY(100);
+
+ if ((READCSR(softc->uart_base+R_UART_IIR) & IIR_FIFO_MASK) != IIR_FIFO_MASK) {
+ WRITECSR(softc->uart_base+R_UART_FIFO,0);
+ }
+ ns16550_uart_setflow(softc);
+
+ return 0;
+}
+
+static int ns16550_uart_read(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ ns16550_uart_t *softc = ctx->dev_softc;
+ unsigned char *bptr;
+ int blen;
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+
+ while ((blen > 0) && (READCSR(softc->uart_base+R_UART_LSR) & LSR_RXRDY)) {
+ *bptr++ = (READCSR(softc->uart_base+R_UART_DATA) & 0xFF);
+ blen--;
+ }
+
+ buffer->buf_retlen = buffer->buf_length - blen;
+ return 0;
+}
+
+static int ns16550_uart_inpstat(cfe_devctx_t *ctx, iocb_inpstat_t *inpstat)
+{
+ ns16550_uart_t *softc = ctx->dev_softc;
+
+ inpstat->inp_status = (READCSR(softc->uart_base+R_UART_LSR) & LSR_RXRDY) ? 1 : 0;
+
+ return 0;
+}
+
+static int ns16550_uart_write(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ ns16550_uart_t *softc = ctx->dev_softc;
+ unsigned char *bptr;
+ int blen;
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+ while ((blen > 0) && (READCSR(softc->uart_base+R_UART_LSR) & LSR_TXRDY)) {
+ WRITECSR(softc->uart_base+R_UART_DATA, *bptr++);
+ blen--;
+ }
+
+ buffer->buf_retlen = buffer->buf_length - blen;
+ return 0;
+}
+
+static int ns16550_uart_ioctl(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ ns16550_uart_t *softc = ctx->dev_softc;
+
+ unsigned int *info = (unsigned int *) buffer->buf_ptr;
+
+ switch ((int)buffer->buf_ioctlcmd) {
+ case IOCTL_SERIAL_GETSPEED:
+ *info = softc->uart_speed;
+ break;
+ case IOCTL_SERIAL_SETSPEED:
+ softc->uart_speed = *info;
+ /* NYI */
+ break;
+ case IOCTL_SERIAL_GETFLOW:
+ *info = softc->uart_flowcontrol;
+ break;
+ case IOCTL_SERIAL_SETFLOW:
+ softc->uart_flowcontrol = *info;
+ ns16550_uart_setflow(softc);
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ns16550_uart_close(cfe_devctx_t *ctx)
+{
+ ns16550_uart_t *softc = ctx->dev_softc;
+
+ WRITECSR(softc->uart_base+R_UART_MCR,0);
+
+ return 0;
+}
+
+
diff --git a/cfe/cfe/dev/dev_ns16550_pci.c b/cfe/cfe/dev/dev_ns16550_pci.c
new file mode 100644
index 0000000..021f34c
--- /dev/null
+++ b/cfe/cfe/dev/dev_ns16550_pci.c
@@ -0,0 +1,114 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * NS16550 UART driver (PCI) File: dev_ns16550_pci.c
+ *
+ * This is a console device driver for a PCI NS16550 UART
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+
+#include "pcivar.h"
+#include "pcireg.h"
+
+
+/* Probe routine for real UART driver */
+extern void ns16550_uart_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+/* Probe routine for this UART driver. */
+static void ns16550pci_uart_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+/* We just glom onto the dispatch table in the real driver */
+extern const cfe_devdisp_t ns16550_uart_dispatch;
+
+const cfe_driver_t ns16550pci_uart = {
+ "PCI NS16550 UART",
+ "uart",
+ CFE_DEV_SERIAL,
+ &ns16550_uart_dispatch,
+ ns16550pci_uart_probe
+};
+
+
+static void ns16550pci_uart_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ phys_addr_t pa;
+ pcitag_t tag;
+ int index = 0;
+
+ /*
+ * NS16550-compatible UART on the PCI bus
+ * probe_a, probe_b and probe_ptr are unused.
+ */
+
+ /*
+ * This is for a SIIG card. Should probably do a little
+ * vendor ID table like we did for the IDE driver so
+ * we can spport other cards.
+ */
+
+ for (;;) {
+
+ if (pci_find_device(0x131f,0x2000,index,&tag) != 0) {
+ break;
+ }
+
+ pci_map_io(tag, PCI_MAPREG(0), PCI_MATCH_BYTES, &pa);
+ xprintf("NS16550PCI: I/O mapped registers start at %08X", (uint32_t)pa);
+
+ ns16550_uart_probe(drv,pa,0,NULL);
+
+ index++;
+ }
+}
+
diff --git a/cfe/cfe/dev/dev_null.c b/cfe/cfe/dev/dev_null.c
new file mode 100644
index 0000000..d995919
--- /dev/null
+++ b/cfe/cfe/dev/dev_null.c
@@ -0,0 +1,142 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Null console device File: dev_null.c
+ *
+ * This is a null console device, useful for console-less
+ * operation, or when using chip simulators.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+
+static void nulldrv_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+
+static int nulldrv_open(cfe_devctx_t *ctx);
+static int nulldrv_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int nulldrv_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int nulldrv_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int nulldrv_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int nulldrv_close(cfe_devctx_t *ctx);
+
+const static cfe_devdisp_t nulldrv_dispatch = {
+ nulldrv_open,
+ nulldrv_read,
+ nulldrv_inpstat,
+ nulldrv_write,
+ nulldrv_ioctl,
+ nulldrv_close,
+ NULL,
+ NULL
+};
+
+const cfe_driver_t nulldrv = {
+ "Null console device",
+ "null",
+ CFE_DEV_SERIAL,
+ &nulldrv_dispatch,
+ nulldrv_probe
+};
+
+
+static void nulldrv_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ cfe_attach(drv,NULL,NULL,drv->drv_description);
+}
+
+
+static int nulldrv_open(cfe_devctx_t *ctx)
+{
+/* nulldrv_t *softc = ctx->dev_softc; */
+
+ return 0;
+}
+
+static int nulldrv_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+/* nulldrv_t *softc = ctx->dev_softc; */
+
+ buffer->buf_retlen = buffer->buf_length;
+ return 0;
+}
+
+static int nulldrv_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
+{
+/* nulldrv_t *softc = ctx->dev_softc; */
+
+ inpstat->inp_status = 0;
+
+ return 0;
+}
+
+static int nulldrv_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+/* nulldrv_t *softc = ctx->dev_softc; */
+
+ buffer->buf_retlen = buffer->buf_length;
+ return 0;
+}
+
+static int nulldrv_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+/* nulldrv_t *softc = ctx->dev_softc;*/
+
+ return -1;
+}
+
+static int nulldrv_close(cfe_devctx_t *ctx)
+{
+/* nulldrv_t *softc = ctx->dev_softc; */
+
+ return 0;
+}
+
+
diff --git a/cfe/cfe/dev/dev_promice.c b/cfe/cfe/dev/dev_promice.c
new file mode 100644
index 0000000..fe79086
--- /dev/null
+++ b/cfe/cfe/dev/dev_promice.c
@@ -0,0 +1,402 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * PromICE console device File: dev_promice.c
+ *
+ * This device driver supports Grammar Engine's PromICE AI2
+ * serial communications options. With this console, you can
+ * communicate with the firmware using only uncached reads in the
+ * boot ROM space. See Grammar Engine's PromICE manuals
+ * for more information at http://www.gei.com
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+/*
+ * Example PromICE initialization file:
+ *
+ * -----------------------
+ * output=com1
+ * pponly=lpt1
+ * rom=27040
+ * word=8
+ * file=cfe.srec
+ * ailoc 7FC00,9600
+ * -----------------------
+ *
+ * The offset specified in the 'ailoc' line must be the location where you
+ * will configure the AI2 serial port. In this example, the ROM is assumed
+ * to be 512KB, and the AI2 serial port is at 511KB, or offset 0x7FC00.
+ * This area is filled with 0xCC to detect AI2's initialization sequence
+ * properly (see the PromICE manual). You should connect your
+ * PromICE's serial port up to the PC and run a terminal emulator on it.
+ * The parallel port will be used for downloading data to the PromICE.
+ *
+ * If you have connected the write line to the PromICE, then you can
+ * define the _AIDIRT_ symbol to increase performance.
+ */
+
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "addrspace.h"
+
+#define _AIDIRT_
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+static void promice_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+
+static int promice_open(cfe_devctx_t *ctx);
+static int promice_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int promice_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int promice_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int promice_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int promice_close(cfe_devctx_t *ctx);
+
+/* *********************************************************************
+ * Device dispatch table
+ ********************************************************************* */
+
+const static cfe_devdisp_t promice_dispatch = {
+ promice_open,
+ promice_read,
+ promice_inpstat,
+ promice_write,
+ promice_ioctl,
+ promice_close,
+ NULL,
+ NULL
+};
+
+/* *********************************************************************
+ * Device descriptor
+ ********************************************************************* */
+
+const cfe_driver_t promice_uart = {
+ "PromICE AI2 Serial Port",
+ "promice",
+ CFE_DEV_SERIAL,
+ &promice_dispatch,
+ promice_probe
+};
+
+/* *********************************************************************
+ * Local constants and structures
+ ********************************************************************* */
+
+/*
+ * If your PromICE is connected to a 32-bit host (emulating four
+ * flash ROMs) and the SB1250 is set to boot from that host, define
+ * the PROMICE_32BITS symbol to make sure the AI2 interface is
+ * configured correctly.
+ */
+
+/*#define PROMICE_32BITS*/
+
+#ifdef PROMICE_32BITS
+#define WORDSIZE 4
+#define WORDTYPE uint32_t
+#else
+#define WORDSIZE 1
+#define WORDTYPE uint8_t
+#endif
+
+
+#define ZERO_OFFSET (0)
+#define ONE_OFFSET (1)
+#define DATA_OFFSET (2)
+#define STATUS_OFFSET (3)
+
+#define TDA 0x01 /* Target data available */
+#define HDA 0x02 /* Host data available */
+#define OVR 0x04 /* Host data overflow */
+
+typedef struct promice_s {
+ unsigned long ai2_addr;
+ unsigned int ai2_wordsize;
+ volatile WORDTYPE *zero;
+ volatile WORDTYPE *one;
+ volatile WORDTYPE *data;
+ volatile WORDTYPE *status;
+} promice_t;
+
+
+/* *********************************************************************
+ * promice_probe(drv,probe_a,probe_b,probe_ptr)
+ *
+ * Device "Probe" routine. This routine creates the soft
+ * context for the device and calls the attach routine.
+ *
+ * Input parameters:
+ * drv - driver structure
+ * probe_a,probe_b,probe_ptr - probe args
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+static void promice_probe(cfe_driver_t *drv,
+ unsigned long probe_a,
+ unsigned long probe_b,
+ void *probe_ptr)
+{
+ promice_t *softc;
+ char descr[80];
+
+ /*
+ * probe_a is the address in the ROM of the AI2 interface
+ * on the PromICE.
+ * probe_b is the word size (1,2,4)
+ */
+
+ softc = (promice_t *) KMALLOC(sizeof(promice_t),0);
+ if (softc) {
+ softc->ai2_addr = probe_a;
+ if (probe_b) softc->ai2_wordsize = probe_b;
+ else softc->ai2_wordsize = WORDSIZE;
+ xsprintf(descr,"%s at 0x%X",drv->drv_description,probe_a);
+ cfe_attach(drv,softc,NULL,descr);
+ }
+}
+
+
+
+/* *********************************************************************
+ * promice_open(ctx)
+ *
+ * Open the device
+ *
+ * Input parameters:
+ * ctx - device context
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+static int promice_open(cfe_devctx_t *ctx)
+{
+ promice_t *softc = ctx->dev_softc;
+ uint8_t dummy;
+
+ softc->zero = (volatile WORDTYPE *)
+ UNCADDR(softc->ai2_addr + (ZERO_OFFSET*softc->ai2_wordsize));
+ softc->one = (volatile WORDTYPE *)
+ UNCADDR(softc->ai2_addr + (ONE_OFFSET*softc->ai2_wordsize));
+ softc->data = (volatile WORDTYPE *)
+ UNCADDR(softc->ai2_addr + (DATA_OFFSET*softc->ai2_wordsize));
+ softc->status = (volatile WORDTYPE *)
+ UNCADDR(softc->ai2_addr + (STATUS_OFFSET*softc->ai2_wordsize));
+
+ /*
+ * Wait for bit 3 to clear so we know the interface is ready.
+ */
+
+ while (*(softc->status) == 0xCC) ; /* NULL LOOP */
+
+ /*
+ * a dummy read is required to clear out the interface.
+ */
+
+ dummy = *(softc->data);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * promice_read(ctx,buffer)
+ *
+ * Read data from the device
+ *
+ * Input parameters:
+ * ctx - device context
+ * buffer - I/O buffer descriptor
+ *
+ * Return value:
+ * number of bytes transferred, or <0 if error
+ ********************************************************************* */
+static int promice_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ promice_t *softc = ctx->dev_softc;
+ unsigned char *bptr;
+ int blen;
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+
+ while ((blen > 0) && (*(softc->status) & HDA)) {
+ *bptr++ = *(softc->data);
+ blen--;
+ }
+
+ buffer->buf_retlen = buffer->buf_length - blen;
+ return 0;
+}
+
+/* *********************************************************************
+ * promice_inpstat(ctx,inpstat)
+ *
+ * Determine if read data is available
+ *
+ * Input parameters:
+ * ctx - device context
+ * inpstat - input status structure
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int promice_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
+{
+ promice_t *softc = ctx->dev_softc;
+
+ inpstat->inp_status = (*(softc->status) & HDA) ? 1 : 0;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * promice_write(ctx,buffer)
+ *
+ * Write data to the device
+ *
+ * Input parameters:
+ * ctx - device context
+ * buffer - I/O buffer descriptor
+ *
+ * Return value:
+ * number of bytes transferred, or <0 if error
+ ********************************************************************* */
+static int promice_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ promice_t *softc = ctx->dev_softc;
+ unsigned char *bptr;
+ int blen;
+ uint8_t data;
+#ifndef _AIDIRT_
+ uint8_t dummy;
+ int count;
+#endif
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+
+
+ /*
+ * The AI2 interface requires you to transmit characters
+ * one bit at a time. First a '1' start bit,
+ * then 8 data bits (lsb first) then another '1' stop bit.
+ *
+ * Just reference the right memory location to transmit a bit.
+ */
+
+ while ((blen > 0) && !(*(softc->status) & TDA)) {
+
+#ifdef _AIDIRT_
+ data = *bptr++;
+ *(softc->zero) = data;
+#else
+ dummy = *(softc->one); /* send start bit */
+
+ data = *bptr++;
+
+ for (count = 0; count < 8; count++) {
+ if (data & 1) dummy = *(softc->one);
+ else dummy = *(softc->zero);
+ data >>= 1; /* shift in next bit */
+ }
+
+ dummy = *(softc->one); /* send stop bit */
+#endif
+
+ blen--;
+ }
+
+ buffer->buf_retlen = buffer->buf_length - blen;
+ return 0;
+}
+
+/* *********************************************************************
+ * promice_ioctl(ctx,buffer)
+ *
+ * Do I/O control operations
+ *
+ * Input parameters:
+ * ctx - device context
+ * buffer - I/O control args
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int promice_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ return -1;
+}
+
+/* *********************************************************************
+ * promice_close(ctx)
+ *
+ * Close the device.
+ *
+ * Input parameters:
+ * ctx - device context
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int promice_close(cfe_devctx_t *ctx)
+{
+ return 0;
+}
+
+
diff --git a/cfe/cfe/dev/dev_sp1011.c b/cfe/cfe/dev/dev_sp1011.c
new file mode 100644
index 0000000..8e0d16b
--- /dev/null
+++ b/cfe/cfe/dev/dev_sp1011.c
@@ -0,0 +1,151 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * SP1011 (Sturgeon) Support File: dev_sp1011.c
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+
+#include "pcireg.h"
+#include "pcivar.h"
+
+extern int eoi_implemented;
+
+void sturgeon_setup (pcitag_t tag, pci_flags_t flags);
+
+
+/* Sturgeon LDT-to-PCI bridge (LPB) specific definitions. */
+
+#define PCI_VENDOR_API 0x14d9
+#define PCI_PRODUCT_API_STURGEON 0x0010
+
+/* Sturgeon specific registers */
+#define LPB_READ_CTRL_REG 0x60
+#define LPB_READ_CTRL_MASK 0xffffff
+
+#define LPB_READ_CTRL_PREF_EN (1 << 0)
+#define LPB_READ_CTRL_RD_PREF_EN (1 << 1)
+#define LPB_READ_CTRL_MULT_PREF_SHIFT 2
+#define LPB_READ_CTRL_MULT_PREF_MASK (7 << LPB_READ_CTRL_MULT_PREF_SHIFT)
+#define LPB_READ_CTRL_LINE_PREF_SHIFT 5
+#define LPB_READ_CTRL_LINE_PREF_MASK (7 << LPB_READ_CTRL_LINE_PREF_SHIFT)
+#define LPB_READ_CTRL_DEL_REQ_SHIFT 8
+#define LPB_READ_CTRL_DEL_REQ_MASK (3 << LPB_READ_CTRL_DEL_REQ_SHIFT)
+
+#define LPB_INT_CTRL_BASE 0xa0
+
+#define LPB_INT_CTRL_ENABLE (1 << 15)
+#define LPB_INT_CTRL_DESTMODE (1 << 14)
+#define LPB_INT_CTRL_DEST_SHIFT 6
+#define LPB_INT_CTRL_DEST_MASK (0xff << LPB_INT_CTRL_DEST_SHIFT)
+#define LPB_INT_CTRL_MSGTYPE_SHIFT 4
+#define LPB_INT_CTRL_MSGTYPE_MASK (0x3 << LPB_INT_CTRL_MSGTYPE_SHIFT)
+#define LPB_INT_CTRL_POLARITY (1 << 3)
+#define LPB_INT_CTRL_TRIGGERMODE (1 << 2)
+#define LPB_INT_CTRL_VECTOR_SHIFT 0
+#define LPB_INT_CTRL_VECTOR_MASK (0x3 << 0)
+
+#define LPB_INT_BLOCK1_REG 0xc4
+
+void
+sturgeon_setup (pcitag_t tag, pci_flags_t flags)
+{
+ int bus, device, function;
+ int secondary;
+ struct pci_bus *pb;
+ unsigned offset;
+ pcireg_t t, ctrl, intmap;
+
+ pci_break_tag(tag, &bus, &device, &function);
+
+ secondary = (pci_conf_read(tag, PPB_BUSINFO_REG) >> 8) & 0xff;
+ pb = &_pci_bus[secondary];
+
+ /* set up READ CONTROL register for selected prefetch option */
+ ctrl = pci_conf_read(tag, LPB_READ_CTRL_REG) & ~LPB_READ_CTRL_MASK;
+ if ((flags & PCI_FLG_LDT_PREFETCH) != 0) {
+ /* Prefetch enable: all cycle types, 2 delayed requests,
+ 4 lines of fetch ahead for MemRdMult */
+ ctrl |= (LPB_READ_CTRL_PREF_EN
+ | LPB_READ_CTRL_RD_PREF_EN
+ | (3 << LPB_READ_CTRL_MULT_PREF_SHIFT)
+ | (1 << LPB_READ_CTRL_DEL_REQ_SHIFT));
+ } else {
+ /* No prefetch */
+ ctrl |= 0;
+ }
+ pci_conf_write(tag, LPB_READ_CTRL_REG, ctrl);
+
+ /* It's apparently not possible for software to distinguish
+ the CSWARM's debug Sturgeon (which has floating interrupt
+ inputs), so we route interrupts only if there are secondary
+ devices. */
+ if (pb->ndev > 0) {
+ /* Setup interrupt mapping for Block 1:
+ Enabled, Dest=Logical (CPU 0 + CPU 1), Type=Fixed */
+ intmap = (LPB_INT_CTRL_ENABLE |
+ LPB_INT_CTRL_DESTMODE | /* Logical */
+ (0x3 << LPB_INT_CTRL_DEST_SHIFT) | /* CPU 0+1 */
+ (0x0 << LPB_INT_CTRL_MSGTYPE_SHIFT)); /* Fixed */
+ if (eoi_implemented) {
+ /* Passes >=2 have working EOI. Trigger=Level */
+ intmap |= LPB_INT_CTRL_TRIGGERMODE; /* Level */
+ } else {
+ /* Pass 1 lacks working EOI. Trigger=Edge */
+ intmap |= 0; /* Edge */
+ }
+
+ offset = pb->inta_shift % 4;
+ t = (intmap + offset);
+ offset = (offset+1) % 4;
+ t |= (intmap + offset) << 16;
+ pci_conf_write(tag, LPB_INT_CTRL_BASE + 8, t);
+
+ offset = (offset+1) % 4;
+ t = (intmap + offset);
+ offset = (offset+1) % 4;
+ t |= (intmap + offset) << 16;
+ pci_conf_write(tag, LPB_INT_CTRL_BASE + 12, t);
+
+ t = pci_conf_read(tag, LPB_INT_BLOCK1_REG);
+ t &= 0xffffff00;
+ t |= (0x40 | (56 >> 2));
+ pci_conf_write(tag, LPB_INT_BLOCK1_REG, t);
+ }
+}
diff --git a/cfe/cfe/dev/dev_tulip.c b/cfe/cfe/dev/dev_tulip.c
new file mode 100644
index 0000000..dec6b56
--- /dev/null
+++ b/cfe/cfe/dev/dev_tulip.c
@@ -0,0 +1,2985 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * DC21x4x Ethernet Driver File: dev_tulip.c
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "sbmips.h"
+
+#ifndef _SB_MAKE64
+#define _SB_MAKE64(x) ((uint64_t)(x))
+#endif
+#ifndef _SB_MAKEMASK1
+#define _SB_MAKEMASK1(n) (_SB_MAKE64(1) << _SB_MAKE64(n))
+#endif
+
+#include "lib_types.h"
+#include "lib_hssubr.h"
+#include "lib_malloc.h"
+#include "lib_string.h"
+#define blockcopy memcpy
+#include "lib_printf.h"
+#include "lib_queue.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+#include "cfe_timer.h"
+#include "cfe_error.h"
+#include "cfe_irq.h"
+
+#include "pcivar.h"
+#include "pcireg.h"
+
+#include "dc21143.h"
+#include "mii.h"
+
+/* This is a driver for specific configurations of the DC21040, DC21041,
+ DC21140A and DC21143, not a generic Tulip driver. The prefix
+ "tulip_" is used to indicate generic Tulip functions, while
+ "dc21040_", "dc21041_", "dc21140_" or "dc21143_" indicates functions
+ specific to a chip variant.
+
+ The 21041 driver assumes a 10BT HD interface, since autonegotiation
+ is known to be broken in the early revisons of that chip. Example
+ cards come from DEC and SMC. Essentially the same driver is used
+ for 21040 cards.
+
+ The 21140 driver assumes that the PHY uses a standard MII interface
+ for both 100BT and 10BT. Example cards come from DEC (National DP83840
+ plus Twister PHY) and Netgear (Level One PHY).
+
+ Some early 21140 boards are exceptions and use SYM plus SRL
+ with different PHY chips for 10 and 100 (limited support).
+
+ The 21143 driver assumes by default that the PHY uses the SYM ("5
+ wire") interface for 100BT with pass-through for 10BT. Example
+ cards come from DEC (MicroLinear ML6694 PHY) and Znyx (QS6611 or
+ Kendin KS8761 PHY). It also supports an MII interface for
+ recognized adapters. An example card comes from Adaptec (National
+ DP83840A and Twister PHY). There is no support for AUI interfaces.
+
+ This SB1250 version takes advantage of DMA coherence and uses
+ "preserve bit lanes" addresses for all accesses that cross the
+ ZBbus-PCI bridge. */
+
+#ifndef TULIP_DEBUG
+#define TULIP_DEBUG 0
+#endif
+
+#ifndef TULIP_TUNE
+#define TULIP_TUNE 1
+#endif
+
+/* Set IPOLL to drive processing through the pseudo-interrupt
+ dispatcher. Set XPOLL to drive processing by an external polling
+ agent. Setting both is ok. */
+
+#ifndef IPOLL
+#define IPOLL 0
+#endif
+#ifndef XPOLL
+#define XPOLL 1
+#endif
+
+#define ENET_ADDR_LEN 6 /* size of an ethernet address */
+#define MAX_ETHER_PACK 1518 /* max size of a packet */
+#define CRC_SIZE 4 /* size of CRC field */
+
+/* Packet buffers. For tulip, the packet must be aligned to a 32-bit
+ word boundary, and we would like it aligned to a cache line
+ boundary for performance. */
+
+#define CACHE_ALIGN 32
+
+#if __long64
+typedef struct eth_pkt_s {
+ queue_t next; /* 16 */
+ uint8_t *buffer; /* 8 */
+ uint32_t flags; /* 4 */
+ int32_t length; /* 4 */
+ uint8_t data[MAX_ETHER_PACK];
+} eth_pkt_t;
+#else
+typedef struct eth_pkt_s {
+ queue_t next; /* 8 */
+ uint8_t *buffer; /* 4 */
+ uint32_t flags; /* 4 */
+ int32_t length; /* 4 */
+ uint32_t unused[3]; /* 12 */
+ uint8_t data[MAX_ETHER_PACK];
+} eth_pkt_t;
+#endif
+
+#define ETH_PKTBUF_LINES ((sizeof(eth_pkt_t) + (CACHE_ALIGN-1))/CACHE_ALIGN)
+#define ETH_PKTBUF_SIZE (ETH_PKTBUF_LINES*CACHE_ALIGN)
+#define ETH_PKTBUF_OFFSET (offsetof(eth_pkt_t, data))
+
+#define ETH_PKT_BASE(data) ((eth_pkt_t *)((data) - ETH_PKTBUF_OFFSET))
+
+/* packet flags */
+#define ETH_TX_SETUP 1 /* assumes Perfect Filtering format */
+
+static void
+show_packet(char c, eth_pkt_t *pkt)
+{
+ int i;
+ int n = (pkt->length < 32 ? pkt->length : 32);
+
+ xprintf("%c[%4d]:", c, pkt->length);
+ for (i = 0; i < n; i++) {
+ if (i % 4 == 0)
+ xprintf(" ");
+ xprintf("%02x", pkt->buffer[i]);
+ }
+ xprintf("\n");
+}
+
+
+/* Descriptor structures */
+
+typedef struct rx_dscr {
+ uint32_t rxd_flags;
+ uint32_t rxd_bufsize;
+ pci_addr_t rxd_bufaddr1;
+ pci_addr_t rxd_bufaddr2;
+} rx_dscr;
+
+typedef struct tx_dscr {
+ uint32_t txd_flags;
+ uint32_t txd_bufsize;
+ pci_addr_t txd_bufaddr1;
+ pci_addr_t txd_bufaddr2;
+} tx_dscr;
+
+/* CAM structure */
+
+typedef union {
+ struct {
+ uint32_t physical[CAM_PERFECT_ENTRIES][3];
+ } p;
+ struct {
+ uint32_t hash[32];
+ uint32_t mbz[7];
+ uint32_t physical[3];
+ } h;
+} tulip_cam;
+
+
+/* Driver data structures */
+
+typedef enum {
+ eth_state_uninit,
+ eth_state_setup,
+ eth_state_off,
+ eth_state_on,
+ eth_state_broken
+} eth_state_t;
+
+#define ETH_PKTPOOL_SIZE 32
+#define ETH_PKT_SIZE MAX_ETHER_PACK
+
+typedef struct tulip_softc {
+ uint32_t membase;
+ uint8_t irq; /* interrupt mapping (used if IPOLL) */
+ pcitag_t tag; /* tag for configuration registers */
+
+ uint8_t hwaddr[ENET_ADDR_LEN];
+ uint16_t device; /* chip device code */
+ uint8_t revision; /* chip revision and step (Table 3-7) */
+
+ /* current state */
+ eth_state_t state;
+
+ /* These fields are the chip startup values. */
+// uint16_t media; /* media type */
+ uint32_t opmode; /* operating mode */
+ uint32_t intmask; /* interrupt mask */
+ uint32_t gpdata; /* output bits for csr15 (21143) */
+
+ /* These fields are set before calling dc21x4x_hwinit */
+ int linkspeed; /* encodings from cfe_ioctl */
+ int loopback;
+
+ /* Packet free list */
+ queue_t freelist;
+ uint8_t *pktpool;
+ queue_t rxqueue;
+
+ /* The descriptor tables */
+ uint8_t *rxdscrmem; /* receive descriptors */
+ uint8_t *txdscrmem; /* transmit descriptors */
+
+ /* These fields keep track of where we are in tx/rx processing */
+ volatile rx_dscr *rxdscr_start; /* beginning of ring */
+ volatile rx_dscr *rxdscr_end; /* end of ring */
+ volatile rx_dscr *rxdscr_remove; /* next one we expect tulip to use */
+ volatile rx_dscr *rxdscr_add; /* next place to put a buffer */
+ int rxdscr_onring;
+
+ volatile tx_dscr *txdscr_start; /* beginning of ring */
+ volatile tx_dscr *txdscr_end; /* end of ring */
+ volatile tx_dscr *txdscr_remove; /* next one we will use for tx */
+ volatile tx_dscr *txdscr_add; /* next place to put a buffer */
+
+ cfe_devctx_t *devctx;
+
+ /* These fields describe the PHY */
+ enum {SRL, MII, SYM} phy_type;
+ int mii_addr;
+
+ /* Statistics */
+ uint32_t inpkts;
+ uint32_t outpkts;
+ uint32_t interrupts;
+ uint32_t rx_interrupts;
+ uint32_t tx_interrupts;
+ uint32_t bus_errors;
+} tulip_softc;
+
+
+/* Entry to and exit from critical sections (currently relative to
+ interrupts only, not SMP) */
+
+#if CFG_INTERRUPTS
+#define CS_ENTER(sc) cfe_disable_irq(sc->irq)
+#define CS_EXIT(sc) cfe_enable_irq(sc->irq)
+#else
+#define CS_ENTER(sc) ((void)0)
+#define CS_EXIT(sc) ((void)0)
+#endif
+
+
+/* Driver parameterization */
+
+#define MAXRXDSCR 32
+#define MAXTXDSCR 32
+#define MINRXRING 8
+
+#define MEDIA_UNKNOWN 0
+#define MEDIA_AUI 1
+#define MEDIA_BNC 2
+#define MEDIA_UTP_FULL_DUPLEX 3
+#define MEDIA_UTP_NO_LINK_TEST 4
+#define MEDIA_UTP 5
+
+/* Prototypes */
+
+static void tulip_ether_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+
+/* Address mapping macros */
+
+/* Note that PTR_TO_PHYS only works with 32-bit addresses, but then
+ so does the Tulip. */
+#define PTR_TO_PHYS(x) (K0_TO_PHYS((uintptr_t)(x)))
+#define PHYS_TO_PTR(a) ((uint8_t *)PHYS_TO_K0(a))
+
+/* All mappings through the PCI host bridge use match bits mode. */
+#define PHYS_TO_PCI(a) ((uint32_t) (a) | 0x20000000)
+#define PCI_TO_PHYS(a) ((uint32_t) (a) & 0x1FFFFFFF)
+
+#define PCI_TO_PTR(a) (PHYS_TO_PTR(PCI_TO_PHYS(a)))
+#define PTR_TO_PCI(x) (PHYS_TO_PCI(PTR_TO_PHYS(x)))
+
+#if __long64
+#define READCSR(sc,csr) \
+ (*((volatile uint32_t *) (PHYS_TO_XKSEG_UNCACHED((sc)->membase + (csr)))))
+
+#define WRITECSR(sc,csr,val) \
+ (*((volatile uint32_t *) \
+ (PHYS_TO_XKSEG_UNCACHED((sc)->membase + (csr)))) = (val))
+
+#else
+#define READCSR(sc,csr) \
+ (hs_read32(PHYS_TO_XKSEG_UNCACHED((sc)->membase + (csr))))
+
+#define WRITECSR(sc,csr,val) \
+ (hs_write32(PHYS_TO_XKSEG_UNCACHED((sc)->membase + (csr)), (val)))
+
+#endif
+
+#define RESET_ADAPTER(sc) \
+ { \
+ WRITECSR((sc), R_CSR_BUSMODE, M_CSR0_SWRESET); \
+ cfe_sleep(CFE_HZ/10); \
+ }
+
+
+/* Debugging */
+
+static void
+dumpstat(tulip_softc *sc)
+{
+ xprintf("-- CSR 5 = %08X CSR 6 = %08x\n",
+ READCSR(sc, R_CSR_STATUS), READCSR(sc, R_CSR_OPMODE));
+}
+
+static void
+dumpcsrs(tulip_softc *sc)
+{
+ int idx;
+
+ xprintf("-------------\n");
+ for (idx = 0; idx < 16; idx++) {
+ xprintf("CSR %2d = %08X\n", idx, READCSR(sc, idx*8));
+ }
+ xprintf("-------------\n");
+}
+
+
+/* Packet management */
+
+/* *********************************************************************
+ * ETH_ALLOC_PKT(sc)
+ *
+ * Allocate a packet from the free list.
+ *
+ * Input parameters:
+ * sc - eth structure
+ *
+ * Return value:
+ * pointer to packet structure, or NULL if none available
+ ********************************************************************* */
+static eth_pkt_t *
+eth_alloc_pkt(tulip_softc *sc)
+{
+ eth_pkt_t *pkt;
+
+ CS_ENTER(sc);
+ pkt = (eth_pkt_t *) q_deqnext(&sc->freelist);
+ CS_EXIT(sc);
+ if (!pkt) return NULL;
+
+ pkt->buffer = pkt->data;
+ pkt->length = ETH_PKT_SIZE;
+ pkt->flags = 0;
+
+ return pkt;
+}
+
+
+/* *********************************************************************
+ * ETH_FREE_PKT(sc,pkt)
+ *
+ * Return a packet to the free list
+ *
+ * Input parameters:
+ * sc - sbmac structure
+ * pkt - packet to return
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void
+eth_free_pkt(tulip_softc *sc, eth_pkt_t *pkt)
+{
+ CS_ENTER(sc);
+ q_enqueue(&sc->freelist, &pkt->next);
+ CS_EXIT(sc);
+}
+
+
+/* *********************************************************************
+ * ETH_INITFREELIST(sc)
+ *
+ * Initialize the buffer free list for this mac. The memory
+ * allocated to the free list is carved up and placed on a linked
+ * list of buffers for use by the mac.
+ *
+ * Input parameters:
+ * sc - eth structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void
+eth_initfreelist(tulip_softc *sc)
+{
+ int idx;
+ uint8_t *ptr;
+ eth_pkt_t *pkt;
+
+ q_init(&sc->freelist);
+
+ ptr = sc->pktpool;
+ for (idx = 0; idx < ETH_PKTPOOL_SIZE; idx++) {
+ pkt = (eth_pkt_t *) ptr;
+ eth_free_pkt(sc, pkt);
+ ptr += ETH_PKTBUF_SIZE;
+ }
+}
+
+
+/* Utilities */
+
+static const char *
+tulip_devname(tulip_softc *sc)
+{
+ return (sc->devctx != NULL ? cfe_device_name(sc->devctx) : "eth?");
+}
+
+
+/* Descriptor ring management */
+
+static int
+tulip_add_rcvbuf(tulip_softc *sc, eth_pkt_t *pkt)
+{
+ volatile rx_dscr *rxd;
+ volatile rx_dscr *nextrxd;
+ uint32_t flags = 0;
+
+ rxd = sc->rxdscr_add;
+
+ /* Figure out where the next descriptor will go */
+ nextrxd = rxd+1;
+ if (nextrxd == sc->rxdscr_end) {
+ nextrxd = sc->rxdscr_start;
+ flags = M_RDES1_ENDOFRING;
+ }
+
+ /*
+ * If the next one is the same as our remove pointer,
+ * the ring is considered full. (it actually has room for
+ * one more, but we reserve the remove == add case for "empty")
+ */
+ if (nextrxd == sc->rxdscr_remove) return -1;
+
+ rxd->rxd_bufsize = V_RDES1_BUF1SIZE(1520) | flags;
+ rxd->rxd_bufaddr1 = PTR_TO_PCI(pkt->buffer);
+ rxd->rxd_bufaddr2 = 0;
+ rxd->rxd_flags = M_RDES0_OWNADAP;
+
+ /* success, advance the pointer */
+ sc->rxdscr_add = nextrxd;
+ CS_ENTER(sc);
+ sc->rxdscr_onring++;
+ CS_EXIT(sc);
+
+ return 0;
+}
+
+static void
+tulip_fillrxring(tulip_softc *sc)
+{
+ eth_pkt_t *pkt;
+
+ while (1) {
+ CS_ENTER(sc);
+ if (sc->rxdscr_onring >= MINRXRING) {
+ CS_EXIT(sc);
+ break;
+ }
+ CS_EXIT(sc);
+ pkt = eth_alloc_pkt(sc);
+ if (pkt == NULL) {
+ /* could not allocate a buffer */
+ break;
+ }
+ if (tulip_add_rcvbuf(sc, pkt) != 0) {
+ /* could not add buffer to ring */
+ eth_free_pkt(sc, pkt);
+ break;
+ }
+ }
+}
+
+
+/* *********************************************************************
+ * TULIP_RX_CALLBACK(sc, pkt)
+ *
+ * Receive callback routine. This routine is invoked when a
+ * buffer queued for receives is filled. In this simple driver,
+ * all we do is add the packet to a per-MAC queue for later
+ * processing, and try to put a new packet in the place of the one
+ * that was removed from the queue.
+ *
+ * Input parameters:
+ * sc - interface
+ * ptk - packet context (eth_pkt structure)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void
+tulip_rx_callback(tulip_softc *sc, eth_pkt_t *pkt)
+{
+ if (TULIP_DEBUG) show_packet('>', pkt); /* debug */
+
+ CS_ENTER(sc);
+ q_enqueue(&sc->rxqueue, &pkt->next);
+ CS_EXIT(sc);
+ sc->inpkts++;
+
+ tulip_fillrxring(sc);
+}
+
+
+static void
+tulip_procrxring(tulip_softc *sc)
+{
+ volatile rx_dscr *rxd;
+ eth_pkt_t *pkt;
+ eth_pkt_t *newpkt;
+ uint32_t flags;
+
+ for (;;) {
+ rxd = (volatile rx_dscr *) sc->rxdscr_remove;
+
+ flags = rxd->rxd_flags;
+ if (flags & M_RDES0_OWNADAP) {
+ /* end of ring, no more packets */
+ break;
+ }
+
+ pkt = ETH_PKT_BASE(PCI_TO_PTR(rxd->rxd_bufaddr1));
+
+ /* Drop error packets */
+ if (flags & M_RDES0_ERRORSUM) {
+ xprintf("%s: rx error %04X\n", tulip_devname(sc), flags & 0xFFFF);
+ tulip_add_rcvbuf(sc, pkt);
+ goto next;
+ }
+
+ /* Pass up the packet */
+ pkt->length = G_RDES0_FRAMELEN(flags) - CRC_SIZE;
+ tulip_rx_callback(sc, pkt);
+
+ /* put a buffer back on the ring to replace this one */
+ newpkt = eth_alloc_pkt(sc);
+ if (newpkt) tulip_add_rcvbuf(sc, newpkt);
+
+next:
+ /* update the pointer, accounting for buffer wrap. */
+ rxd++;
+ if (rxd == sc->rxdscr_end)
+ rxd = sc->rxdscr_start;
+
+ sc->rxdscr_remove = (rx_dscr *) rxd;
+ CS_ENTER(sc);
+ sc->rxdscr_onring--;
+ CS_EXIT(sc);
+ }
+}
+
+
+static int
+tulip_add_txbuf(tulip_softc *sc, eth_pkt_t *pkt)
+{
+ volatile tx_dscr *txd;
+ volatile tx_dscr *nexttxd;
+ uint32_t bufsize = 0;
+
+ txd = sc->txdscr_add;
+
+ /* Figure out where the next descriptor will go */
+ nexttxd = (txd+1);
+ if (nexttxd == sc->txdscr_end) {
+ nexttxd = sc->txdscr_start;
+ bufsize = M_TDES1_ENDOFRING;
+ }
+
+ /* If the next one is the same as our remove pointer,
+ the ring is considered full. (it actually has room for
+ one more, but we reserve the remove == add case for "empty") */
+
+ if (nexttxd == sc->txdscr_remove) return -1;
+
+ bufsize |= V_TDES1_BUF1SIZE(pkt->length) |
+ M_TDES1_FIRSTSEG | M_TDES1_LASTSEG | M_TDES1_INTERRUPT;
+ if (pkt->flags & ETH_TX_SETUP) {
+ /* For a setup packet, FIRSTSEG and LASTSEG should be clear (!) */
+ bufsize ^= M_TDES1_SETUP | M_TDES1_FIRSTSEG | M_TDES1_LASTSEG;
+ }
+ txd->txd_bufsize = bufsize;
+ txd->txd_bufaddr1 = PTR_TO_PCI(pkt->buffer);
+ txd->txd_bufaddr2 = 0;
+ txd->txd_flags = M_TDES0_OWNADAP;
+
+ /* success, advance the pointer */
+ sc->txdscr_add = nexttxd;
+
+ return 0;
+}
+
+
+static int
+tulip_transmit(tulip_softc *sc,eth_pkt_t *pkt)
+{
+ int rv;
+
+ if (TULIP_DEBUG) show_packet('<', pkt); /* debug */
+
+ rv = tulip_add_txbuf(sc, pkt);
+ sc->outpkts++;
+
+ WRITECSR(sc, R_CSR_TXPOLL, 1);
+ return rv;
+}
+
+
+static void
+tulip_proctxring(tulip_softc *sc)
+{
+ volatile tx_dscr *txd;
+ eth_pkt_t *pkt;
+ uint32_t flags;
+
+ for (;;) {
+ txd = (volatile tx_dscr *) sc->txdscr_remove;
+
+ if (txd == sc->txdscr_add) {
+ /* ring is empty, no buffers to process */
+ break;
+ }
+
+ flags = txd->txd_flags;
+ if (flags & M_TDES0_OWNADAP) {
+ /* Reached a packet still being transmitted */
+ break;
+ }
+
+ /* Check for a completed setup packet */
+ pkt = ETH_PKT_BASE(PCI_TO_PTR(txd->txd_bufaddr1));
+ if (pkt->flags & ETH_TX_SETUP) {
+ if (sc->state == eth_state_setup) {
+ uint32_t opmode;
+
+ /* check flag bits */
+ opmode = READCSR(sc, R_CSR_OPMODE);
+ opmode |= M_CSR6_RXSTART;
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+ sc->inpkts = sc->outpkts = 0;
+ sc->state =eth_state_on;
+ }
+ pkt->flags &=~ ETH_TX_SETUP;
+ }
+
+ /* Just free the packet */
+ eth_free_pkt(sc, pkt);
+
+ /* update the pointer, accounting for buffer wrap. */
+ txd++;
+ if (txd == sc->txdscr_end)
+ txd = sc->txdscr_start;
+
+ sc->txdscr_remove = (tx_dscr *) txd;
+ }
+}
+
+
+static void
+tulip_initrings(tulip_softc *sc)
+{
+ volatile tx_dscr *txd;
+ volatile rx_dscr *rxd;
+
+ /* Claim ownership of all descriptors for the driver */
+
+ for (txd = sc->txdscr_start; txd != sc->txdscr_end; txd++)
+ txd->txd_flags = 0;
+ for (rxd = sc->rxdscr_start; rxd != sc->rxdscr_end; rxd++)
+ rxd->rxd_flags = 0;
+
+ /* Init the ring pointers */
+
+ sc->txdscr_add = sc->txdscr_remove = sc->txdscr_start;
+ sc->rxdscr_add = sc->rxdscr_remove = sc->rxdscr_start;
+ sc->rxdscr_onring = 0;
+
+ /* Add stuff to the receive ring */
+
+ tulip_fillrxring(sc);
+}
+
+
+static int
+tulip_init(tulip_softc *sc)
+{
+ /* Allocate descriptor rings */
+ sc->rxdscrmem = KMALLOC(MAXRXDSCR*sizeof(rx_dscr), sizeof(rx_dscr));
+ sc->txdscrmem = KMALLOC(MAXTXDSCR*sizeof(tx_dscr), sizeof(tx_dscr));
+
+ /* Allocate buffer pool */
+ sc->pktpool = KMALLOC(ETH_PKTPOOL_SIZE*ETH_PKTBUF_SIZE, CACHE_ALIGN);
+ eth_initfreelist(sc);
+ q_init(&sc->rxqueue);
+
+ /* Fill in pointers to the rings */
+ sc->rxdscr_start = (rx_dscr *) (sc->rxdscrmem);
+ sc->rxdscr_end = sc->rxdscr_start + MAXRXDSCR;
+ sc->rxdscr_add = sc->rxdscr_start;
+ sc->rxdscr_remove = sc->rxdscr_start;
+ sc->rxdscr_onring = 0;
+
+ sc->txdscr_start = (tx_dscr *) (sc->txdscrmem);
+ sc->txdscr_end = sc->txdscr_start + MAXTXDSCR;
+ sc->txdscr_add = sc->txdscr_start;
+ sc->txdscr_remove = sc->txdscr_start;
+
+ tulip_initrings(sc);
+
+ return 0;
+}
+
+
+static void
+tulip_resetrings(tulip_softc *sc)
+{
+ volatile tx_dscr *txd;
+ volatile rx_dscr *rxd;
+ eth_pkt_t *pkt;
+
+ /* Free already-sent descriptors and buffers */
+ tulip_proctxring(sc);
+
+ /* Free any pending but unsent */
+ txd = (volatile tx_dscr *) sc->txdscr_remove;
+ while (txd != sc->txdscr_add) {
+ txd->txd_flags &=~ M_TDES0_OWNADAP;
+ pkt = ETH_PKT_BASE(PCI_TO_PTR(txd->txd_bufaddr1));
+ eth_free_pkt(sc, pkt);
+
+ txd++;
+ if (txd == sc->txdscr_end)
+ txd = sc->txdscr_start;
+ }
+ sc->txdscr_add = sc->txdscr_remove;
+
+ /* Discard any received packets as well as all free buffers */
+ rxd = (volatile rx_dscr *) sc->rxdscr_remove;
+ while (rxd != sc->rxdscr_add) {
+ rxd->rxd_flags &=~ M_RDES0_OWNADAP;
+ pkt = ETH_PKT_BASE(PCI_TO_PTR(rxd->rxd_bufaddr1));
+ eth_free_pkt(sc, pkt);
+
+ rxd++;
+ if (rxd == sc->rxdscr_end)
+ rxd = sc->rxdscr_start;
+ CS_ENTER(sc);
+ sc->rxdscr_onring--;
+ CS_EXIT(sc);
+ }
+
+ /* Reestablish the initial state. */
+ tulip_initrings(sc);
+}
+
+
+/* CRCs */
+
+#define IEEE_CRC32_POLY 0xEDB88320UL /* CRC-32 Poly -- either endian */
+
+static uint32_t
+tulip_crc32(const uint8_t *databuf, unsigned int datalen)
+{
+ unsigned int idx, bit, data;
+ uint32_t crc;
+
+ crc = 0xFFFFFFFFUL;
+ for (idx = 0; idx < datalen; idx++)
+ for (data = *databuf++, bit = 0; bit < 8; bit++, data >>= 1)
+ crc = (crc >> 1) ^ (((crc ^ data) & 1) ? IEEE_CRC32_POLY : 0);
+ return crc;
+}
+
+#define tulip_mchash(mca) (tulip_crc32((mca), 6) & 0x1FF)
+
+
+/* Serial ROM access */
+
+/****************************************************************************
+ * tulip_spin(sc, ns)
+ *
+ * Spin for a short interval (nominally in nanoseconds)
+ *
+ * Input Parameters: ns - minimum required nsec.
+ *
+ * The delay loop uses uncached PCI reads, each of which requires
+ * at least 3 PCI bus clocks (45 ns at 66 MHz) to complete. The
+ * actual delay will be longer (much longer if preempted).
+ ***************************************************************************/
+
+#define PCI_MIN_DELAY 45
+
+static void
+tulip_spin(tulip_softc *sc, long nanoseconds)
+{
+ long delay;
+ volatile uint32_t t;
+
+ for (delay = nanoseconds; delay > 0; delay -= PCI_MIN_DELAY)
+ t = READCSR(sc, R_CSR_BUSMODE);
+}
+
+
+/*
+ * Delays below are chosen to meet specs for NS93C64 (slow M variant).
+ * Current parts are faster.
+ * Reference: NS Memory Data Book, 1994
+ */
+
+#define SROM_SIZE 128
+#define SROM_MAX_CYCLES 32
+
+#define SROM_CMD_BITS 3
+#define SROM_ADDR_BITS 6
+
+#define K_SROM_READ_CMD 06
+#define K_SROM_WRITE_CMD 05
+
+#define SROM_VENDOR_INDEX 0x00
+#define SROM_FORMAT_INDEX 0x12
+#define SROM_ADDR_INDEX 0x14
+
+#define SROM_DEVICE0_INDEX 0x1A
+#define SROM_LEAF0_OFFSET_INDEX 0x1B
+
+#define SROM_CRC_INDEX (SROM_SIZE-2)
+/* Note recent chips supporting wake-on-lan have CRC in bytes 94, 95 */
+
+#define SROM_WORD(rom,offset) ((rom)[offset] | ((rom)[offset+1] << 8))
+
+static void
+srom_idle_state(tulip_softc *sc)
+{
+ uint32_t csr9;
+ unsigned int i;
+
+ csr9 = READCSR(sc, R_CSR_ROM_MII);
+
+ csr9 |= M_CSR9_SROMCHIPSEL;
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 100); /* CS setup (Tcss=100) */
+
+ /* Run the clock through the maximum number of pending read cycles */
+ for (i = 0; i < SROM_MAX_CYCLES*2; i++) {
+ csr9 ^= M_CSR9_SROMCLOCK;
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 1000); /* SK period (Fsk=0.5MHz) */
+ }
+
+ /* Deassert SROM Chip Select */
+ csr9 &=~ M_CSR9_SROMCHIPSEL;
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 50); /* CS recovery (Tsks=50) */
+}
+
+static void
+srom_send_command_bit(tulip_softc *sc, unsigned int data)
+{
+ uint32_t csr9;
+
+ csr9 = READCSR(sc, R_CSR_ROM_MII);
+
+ /* Place the data bit on the bus */
+ if (data == 1)
+ csr9 |= M_CSR9_SROMDATAIN;
+ else
+ csr9 &=~ M_CSR9_SROMDATAIN;
+
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 360); /* setup: Tdis=200 */
+
+ /* Now clock the data into the SROM */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9 | M_CSR9_SROMCLOCK);
+ tulip_spin(sc, 900); /* clock high, Tskh=500 */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 450); /* clock low, Tskl=250 */
+
+ /* Now clear the data bit */
+ csr9 &=~ M_CSR9_SROMDATAIN; /* data invalid, Tidh=20 for SK^ */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 270); /* min cycle, 1/Fsk=2000 */
+}
+
+static uint16_t
+srom_read_bit(tulip_softc *sc)
+{
+ uint32_t csr9;
+
+ csr9 = READCSR(sc, R_CSR_ROM_MII);
+
+ /* Generate a clock cycle before doing a read */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9 | M_CSR9_SROMCLOCK); /* rising edge */
+ tulip_spin(sc, 1000); /* clock high, Tskh=500, Tpd=1000 */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9); /* falling edge */
+ tulip_spin(sc, 1000); /* clock low, 1/Fsk=2000 */
+
+ csr9 = READCSR(sc, R_CSR_ROM_MII);
+ return ((csr9 & M_CSR9_SROMDATAOUT) != 0 ? 1 : 0);
+}
+
+#define CMD_BIT_MASK (1 << (SROM_CMD_BITS+SROM_ADDR_BITS-1))
+
+static uint16_t
+srom_read_word(tulip_softc *sc, unsigned int index)
+{
+ uint16_t command, word;
+ uint32_t csr9;
+ unsigned int i;
+
+ csr9 = READCSR(sc, R_CSR_ROM_MII) | M_CSR9_SROMCHIPSEL;
+
+ /* Assert the SROM CS line */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 100); /* CS setup, Tcss = 100 */
+
+ /* Send the read command to the SROM */
+ command = (K_SROM_READ_CMD << SROM_ADDR_BITS) | index;
+ for (i = 0; i < SROM_CMD_BITS+SROM_ADDR_BITS; i++) {
+ srom_send_command_bit(sc, (command & CMD_BIT_MASK) != 0 ? 1 : 0);
+ command <<= 1;
+ }
+
+ /* Now read the bits from the SROM (MSB first) */
+ word = 0;
+ for (i = 0; i < 16; ++i) {
+ word <<= 1;
+ word |= srom_read_bit(sc);
+ }
+
+ /* Clear the SROM CS Line, CS hold, Tcsh = 0 */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9 &~ M_CSR9_SROMCHIPSEL);
+
+ return word;
+}
+
+
+/****************************************************************************
+ * srom_calc_crc()
+ *
+ * Calculate the CRC of the SROM and return it. We compute the
+ * CRC per Appendix A of the 21140A ROM/external register data
+ * sheet (EC-QPQWA-TE).
+ ***************************************************************************/
+
+static uint16_t
+srom_calc_crc(tulip_softc *sc, uint8_t srom[], int length)
+{
+ uint32_t crc = tulip_crc32(srom, length) ^ 0xFFFFFFFF;
+
+ return (uint16_t)(crc & 0xFFFF);
+}
+
+/****************************************************************************
+ * srom_read_all(sc, uint8_t dest)
+ *
+ * Read the entire SROM into the srom array
+ *
+ * Input parameters:
+ * sc - tulip state
+ ***************************************************************************/
+
+static int
+srom_read_all(tulip_softc *sc, uint8_t dest[])
+{
+ int i;
+ uint16_t crc, temp;
+
+ WRITECSR(sc, R_CSR_ROM_MII, M_CSR9_SERROMSEL|M_CSR9_ROMREAD);
+
+ srom_idle_state(sc);
+
+ for (i = 0; i < SROM_SIZE/2; i++) {
+ temp = srom_read_word(sc, i);
+ dest[2*i] = temp & 0xFF;
+ dest[2*i+1] =temp >> 8;
+ }
+
+ WRITECSR(sc, R_CSR_ROM_MII, 0); /* CS hold, Tcsh=0 */
+
+ crc = srom_calc_crc(sc, dest, SROM_CRC_INDEX);
+ if (crc != SROM_WORD(dest, SROM_CRC_INDEX)) {
+ crc = srom_calc_crc(sc, dest, 94); /* "alternative" */
+ if (crc != SROM_WORD(dest, 94)) {
+ xprintf("%s: Invalid SROM CRC, calc %04x, stored %04x\n",
+ tulip_devname(sc), crc, SROM_WORD(dest, 94));
+ return 0/*-1*/;
+ }
+ }
+ return 0;
+}
+
+static int
+srom_read_addr(tulip_softc *sc, uint8_t buf[])
+{
+ uint8_t srom[SROM_SIZE];
+
+ if (srom_read_all(sc, srom) == 0) {
+ memcpy(buf, &srom[SROM_ADDR_INDEX], ENET_ADDR_LEN);
+ return 0;
+ }
+
+ return -1;
+}
+
+
+/****************************************************************************
+ * earom_read_all(sc, uint8_t dest)
+ *
+ * Read the entire Ethernet address ROM into the srom array (21040 only)
+ *
+ * Input parameters:
+ * sc - tulip state
+ ***************************************************************************/
+
+static int
+earom_read_all(tulip_softc *sc, uint8_t dest[])
+{
+ int i;
+ uint32_t csr9;
+
+ WRITECSR(sc, R_CSR_ROM_MII, 0); /* reset pointer */
+
+ for (i = 0; i < SROM_SIZE; i++) {
+ for (;;) {
+ csr9 = READCSR(sc, R_CSR_ROM_MII);
+ if ((csr9 & M_CSR9_DATANOTVALID) == 0)
+ break;
+ POLL(); /* XXX need a timeout */
+ }
+ dest[i] = G_CSR9_ROMDATA(csr9);
+ }
+
+ return 0;
+}
+
+static int
+earom_read_addr(tulip_softc *sc, uint8_t buf[])
+{
+ uint8_t srom[SROM_SIZE];
+
+ if (earom_read_all(sc, srom) == 0) {
+ memcpy(buf, &srom[0], ENET_ADDR_LEN);
+ return 0;
+ }
+
+ return -1;
+}
+
+
+static int
+rom_read_all(tulip_softc *sc, uint8_t buf[])
+{
+ if (sc->device == K_PCI_ID_DC21040)
+ return earom_read_all(sc, buf);
+ else
+ return srom_read_all(sc, buf);
+}
+
+static int
+rom_read_addr(tulip_softc *sc, uint8_t buf[])
+{
+ if (sc->device == K_PCI_ID_DC21040)
+ return earom_read_addr(sc, buf);
+ else
+ return srom_read_addr(sc, buf);
+}
+
+#if 0
+static void
+rom_dump(uint8_t srom[])
+{
+ int i;
+
+ xprintf("DC21x4x: SROM data:");
+ for (i = 0; i < SROM_SIZE; i++) {
+ if (i % 16 == 0)
+ xprintf("\n %02x: ", i);
+ xprintf(" %02x", srom[i]);
+ }
+ xprintf("\n");
+}
+#else
+#define rom_dump(srom)
+#endif
+
+
+/****************************************************************************
+ * MII access utility routines
+ ***************************************************************************/
+
+/* MII clock limited to 2.5 MHz, transactions end with MDIO tristated */
+
+static void
+mii_write_bits(tulip_softc *sc, uint32_t data, unsigned int count)
+{
+ uint32_t csr9;
+ uint32_t bitmask;
+
+ csr9 = READCSR(sc, R_CSR_ROM_MII) &~ (M_CSR9_MDC | M_CSR9_MIIMODE);
+
+ for (bitmask = 1 << (count-1); bitmask != 0; bitmask >>= 1) {
+ csr9 &=~ M_CSR9_MDO;
+ if ((data & bitmask) != 0) csr9 |= M_CSR9_MDO;
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+
+ tulip_spin(sc, 2000); /* setup */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9 | M_CSR9_MDC);
+ tulip_spin(sc, 2000); /* hold */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ }
+}
+
+static void
+mii_turnaround(tulip_softc *sc)
+{
+ uint32_t csr9;
+
+ csr9 = READCSR(sc, R_CSR_ROM_MII) | M_CSR9_MIIMODE;
+
+ /* stop driving data */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 2000); /* setup */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9 | M_CSR9_MDC);
+ tulip_spin(sc, 2000); /* clock high */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+
+ /* read back and check for 0 here? */
+}
+
+/****************************************************************************
+ * mii_read_register
+ *
+ * This routine reads a register from the PHY chip using the MII
+ * serial management interface.
+ *
+ * Input parameters:
+ * index - index of register to read (0-31)
+ *
+ * Return value:
+ * word read from register
+ ***************************************************************************/
+
+static uint16_t
+mii_read_register(tulip_softc *sc, unsigned int index)
+{
+ /* Send the command and address to the PHY. The sequence is
+ a synchronization sequence (32 1 bits)
+ a "start" command (2 bits)
+ a "read" command (2 bits)
+ the PHY addr (5 bits)
+ the register index (5 bits)
+ */
+ uint32_t csr9;
+ uint16_t word;
+ int i;
+
+ mii_write_bits(sc, 0xFF, 8);
+ mii_write_bits(sc, 0xFFFFFFFF, 32);
+ mii_write_bits(sc, MII_COMMAND_START, 2);
+ mii_write_bits(sc, MII_COMMAND_READ, 2);
+ mii_write_bits(sc, sc->mii_addr, 5);
+ mii_write_bits(sc, index, 5);
+
+ mii_turnaround(sc);
+
+ csr9 = (READCSR(sc, R_CSR_ROM_MII) &~ M_CSR9_MDC) | M_CSR9_MIIMODE;
+ word = 0;
+
+ for (i = 0; i < 16; i++) {
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 2000); /* clock width low */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9 | M_CSR9_MDC);
+ tulip_spin(sc, 2000); /* clock width high */
+ WRITECSR(sc, R_CSR_ROM_MII, csr9);
+ tulip_spin(sc, 1000); /* output delay */
+ word <<= 1;
+ if ((READCSR(sc, R_CSR_ROM_MII) & M_CSR9_MDI) != 0)
+ word |= 0x0001;
+ }
+
+ return word;
+
+ /* reset to output mode? */
+}
+
+/****************************************************************************
+ * mii_write_register
+ *
+ * This routine writes a register in the PHY chip using the MII
+ * serial management interface.
+ *
+ * Input parameters:
+ * index - index of register to write (0-31)
+ * value - word to write
+ ***************************************************************************/
+
+static void
+mii_write_register(tulip_softc *sc, unsigned int index, uint16_t value)
+{
+ mii_write_bits(sc, 0xFF, 8);
+ mii_write_bits(sc, 0xFFFFFFFF, 32);
+ mii_write_bits(sc, MII_COMMAND_START, 2);
+ mii_write_bits(sc, MII_COMMAND_WRITE, 2);
+ mii_write_bits(sc, sc->mii_addr, 5);
+ mii_write_bits(sc, index, 5);
+ mii_write_bits(sc, MII_COMMAND_ACK, 2);
+ mii_write_bits(sc, value, 16);
+
+ /* reset to input mode? */
+}
+
+
+static int
+mii_probe(tulip_softc *sc)
+{
+ int i;
+ uint16_t id1, id2;
+
+ for (i = 0; i < 32; i++) {
+ sc->mii_addr = i;
+ id1 = mii_read_register(sc, MII_PHYIDR1);
+ id2 = mii_read_register(sc, MII_PHYIDR2);
+ if ((id1 != 0x0000 && id1 != 0xFFFF) ||
+ (id2 != 0x0000 && id2 != 0xFFFF)) {
+ return 0;
+ }
+ }
+ return -1;
+}
+
+#if 0
+#define OUI_NAT_SEMI 0x080017
+#define OUI_LEVEL_ONE 0x1E0400 /* 0x00207B, bit reversed and truncated */
+
+static void
+mii_dump(tulip_softc *sc, const char *label)
+{
+ int i;
+ uint16_t r;
+ uint32_t oui, part;
+
+ xprintf("%s\n", label);
+ oui = 0;
+ for (i = 0; i <= 6; ++i) {
+ r = mii_read_register(sc, i);
+ if (r != 0) xprintf("MII_REG%02x: %04x\n", i, r);
+ if (i == MII_PHYIDR1) {
+ oui = r << 6;
+ }
+ else if (i == MII_PHYIDR2) {
+ oui |= (r >> 10) & 0x3F;
+ part = (r >> 4) & 0x3F;
+ }
+ }
+ if (oui == OUI_NAT_SEMI) { /* DP83840, DP83840A */
+ for (i = 0x15; i <= 0x19; ++i) {
+ r = mii_read_register(sc, i);
+ if (r != 0) xprintf("MII_REG%02x: %04x\n", i, r);
+ }
+ }
+ else if (oui == OUI_LEVEL_ONE) { /* LXT970, etc. */
+ for (i = 0x10; i <= 0x14; ++i) {
+ r = mii_read_register(sc, i);
+ if (r != 0) xprintf("MII_REG%02x: %04x\n", i, r);
+ }
+ }
+}
+#else
+#define mii_dump(sc,label)
+#endif
+
+
+/* The following functions are suitable for all tulips with MII
+ interfaces. */
+
+static void
+mii_set_speed(tulip_softc *sc, int speed, int autoneg)
+{
+ uint16_t control;
+ uint16_t pcr;
+ uint32_t opmode = 0;
+
+ /* This is really just for NS DP83840/A. Needed? */
+ pcr = mii_read_register(sc, 0x17);
+ pcr |= (0x400|0x100|0x40|0x20);
+ mii_write_register(sc, 0x17, pcr);
+
+ control = mii_read_register(sc, MII_BMCR);
+
+ if (!autoneg) {
+ control &=~ (BMCR_ANENABLE | BMCR_RESTARTAN);
+ mii_write_register(sc, MII_BMCR, control);
+ control &=~ (BMCR_SPEED0 | BMCR_SPEED1 | BMCR_DUPLEX);
+ }
+
+ switch (speed) {
+ case ETHER_SPEED_10HDX:
+ default:
+ opmode = M_CSR6_SPEED_10_MII;
+ break;
+ case ETHER_SPEED_10FDX:
+ control |= BMCR_DUPLEX;
+ opmode = M_CSR6_SPEED_10_MII | M_CSR6_FULLDUPLEX;
+ break;
+ case ETHER_SPEED_100HDX:
+ control |= BMCR_SPEED100;
+ opmode = M_CSR6_SPEED_100_MII;
+ break;
+ case ETHER_SPEED_100FDX:
+ control |= BMCR_SPEED100 | BMCR_DUPLEX ;
+ opmode = M_CSR6_SPEED_100_MII | M_CSR6_FULLDUPLEX;
+ break;
+ }
+
+ if (!autoneg)
+ mii_write_register(sc, MII_BMCR, control);
+
+ opmode |= M_CSR6_MBO;
+#if TULIP_TUNE
+ opmode |= V_CSR6_THRESHCONTROL(K_CSR6_TXTHRES_128_72);
+#else
+ opmode |= M_CSR6_STOREFWD;
+#endif
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+ mii_dump(sc, "setspeed PHY");
+}
+
+static void
+mii_autonegotiate(tulip_softc *sc)
+{
+ uint16_t control, status, cap;
+ unsigned int timeout;
+ int linkspeed;
+ int autoneg;
+
+ linkspeed = ETHER_SPEED_UNKNOWN;
+
+ /* Read twice to clear latching bits */
+ status = mii_read_register(sc, MII_BMSR);
+ status = mii_read_register(sc, MII_BMSR);
+ mii_dump(sc, "query PHY");
+
+ if ((status & (BMSR_AUTONEG | BMSR_LINKSTAT)) ==
+ (BMSR_AUTONEG | BMSR_LINKSTAT))
+ control = mii_read_register(sc, MII_BMCR);
+ else {
+ /* reset the PHY */
+ mii_write_register(sc, MII_BMCR, BMCR_RESET);
+ timeout = 3000;
+ for (;;) {
+ control = mii_read_register(sc, MII_BMCR);
+ if ((control && BMCR_RESET) == 0) break;
+ cfe_sleep(CFE_HZ/2);
+ timeout -= 500;
+ if (timeout <= 0) break;
+ }
+ if ((control & BMCR_RESET) != 0) {
+ xprintf("%s: PHY reset failed\n", tulip_devname(sc));
+ return;
+ }
+
+ status = mii_read_register(sc, MII_BMSR);
+ cap = ((status >> 6) & (ANAR_TXFD | ANAR_TXHD | ANAR_10FD | ANAR_10HD))
+ | PSB_802_3;
+ mii_write_register(sc, MII_ANAR, cap);
+ control |= (BMCR_ANENABLE | BMCR_RESTARTAN);
+ mii_write_register(sc, MII_BMCR, control);
+
+ timeout = 3000;
+ for (;;) {
+ status = mii_read_register(sc, MII_BMSR);
+ if ((status & BMSR_ANCOMPLETE) != 0) break;
+ cfe_sleep(CFE_HZ/2);
+ timeout -= 500;
+ if (timeout <= 0) break;
+ }
+ mii_dump(sc, "done PHY");
+ }
+
+ xprintf("%s: Link speed: ", tulip_devname(sc));
+ if ((status & BMSR_ANCOMPLETE) != 0) {
+ /* A link partner was negogiated... */
+
+ uint16_t remote = mii_read_register(sc, MII_ANLPAR);
+
+ autoneg = 1;
+ if ((remote & ANLPAR_TXFD) != 0) {
+ xprintf("100BaseT FDX");
+ linkspeed = ETHER_SPEED_100FDX;
+ }
+ else if ((remote & ANLPAR_TXHD) != 0) {
+ xprintf("100BaseT HDX");
+ linkspeed = ETHER_SPEED_100HDX;
+ }
+ else if ((remote & ANLPAR_10FD) != 0) {
+ xprintf("10BaseT FDX");
+ linkspeed = ETHER_SPEED_10FDX;
+ }
+ else if ((remote & ANLPAR_10HD) != 0) {
+ xprintf("10BaseT HDX");
+ linkspeed = ETHER_SPEED_10HDX;
+ }
+ xprintf("\n");
+ }
+ else {
+ /* no link partner negotiation */
+
+ autoneg = 0;
+ xprintf("Unknown, assuming 10BaseT\n");
+ control &=~ (BMCR_ANENABLE | BMCR_RESTARTAN);
+ mii_write_register(sc, MII_BMCR, control);
+ linkspeed = ETHER_SPEED_10HDX;
+ }
+
+ if ((status & BMSR_LINKSTAT) == 0)
+ mii_write_register(sc, MII_BMCR, control);
+ mii_set_speed(sc, linkspeed, autoneg);
+
+ status = mii_read_register(sc, MII_BMSR); /* clear latching bits */
+ mii_dump(sc, "final PHY");
+}
+
+
+/* Chip specific code */
+
+static void
+dc21143_set_speed(tulip_softc *sc, int speed)
+{
+ uint32_t opmode = 0;
+
+ WRITECSR(sc, R_CSR_SIAMODE0, 0);
+
+ switch (speed) {
+ case ETHER_SPEED_AUTO:
+ break;
+ case ETHER_SPEED_10HDX:
+ default:
+ WRITECSR(sc, R_CSR_SIAMODE1, M_CSR14_10BT_HD);
+ WRITECSR(sc, R_CSR_SIAMODE2, sc->gpdata);
+ opmode = M_CSR6_SPEED_10;
+ break;
+ case ETHER_SPEED_10FDX:
+ WRITECSR(sc, R_CSR_SIAMODE1, M_CSR14_10BT_FD);
+ WRITECSR(sc, R_CSR_SIAMODE2, sc->gpdata);
+ opmode = M_CSR6_SPEED_10 | M_CSR6_FULLDUPLEX;
+ break;
+ case ETHER_SPEED_100HDX:
+ WRITECSR(sc, R_CSR_SIAMODE1, 0);
+ WRITECSR(sc, R_CSR_SIAMODE2, sc->gpdata);
+ opmode = M_CSR6_SPEED_100;
+ break;
+ case ETHER_SPEED_100FDX:
+ WRITECSR(sc, R_CSR_SIAMODE1, 0);
+ WRITECSR(sc, R_CSR_SIAMODE2, sc->gpdata);
+ opmode = M_CSR6_SPEED_100 | M_CSR6_FULLDUPLEX;
+ break;
+ }
+
+ WRITECSR(sc, R_CSR_SIAMODE0, M_CSR13_CONN_NOT_RESET);
+
+ opmode |= M_CSR6_MBO;
+#if TULIP_TUNE
+ opmode |= V_CSR6_THRESHCONTROL(K_CSR6_TXTHRES_128_72);
+#else
+ opmode |= M_CSR6_STOREFWD;
+#endif
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+}
+
+static void
+dc21143_autonegotiate(tulip_softc *sc)
+{
+ uint32_t opmode;
+ uint32_t tempword;
+ int count;
+ int linkspeed;
+
+ linkspeed = ETHER_SPEED_UNKNOWN;
+
+ /* Program the media setup into the CSRs. */
+ /* reset SIA */
+ WRITECSR(sc, R_CSR_SIAMODE0, 0);
+
+ /* set to speed_10, fullduplex to start_nway */
+ opmode =
+ M_CSR6_SPEED_10 |
+ M_CSR6_FULLDUPLEX |
+ M_CSR6_MBO;
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+
+ /* Choose advertised capabilities */
+ tempword =
+ M_CSR14_100BASETHALFDUP |
+ M_CSR14_100BASETFULLDUP |
+ M_CSR14_HALFDUPLEX10BASET;
+ WRITECSR(sc, R_CSR_SIAMODE1, tempword);
+
+ /* Enable autonegotiation */
+ tempword |= M_CSR14_AUTONEGOTIATE | 0xFFFF;
+ WRITECSR(sc, R_CSR_SIAMODE1, tempword);
+ WRITECSR(sc, R_CSR_SIAMODE2, sc->gpdata);
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+ WRITECSR(sc, R_CSR_SIAMODE0, M_CSR13_CONN_NOT_RESET);
+
+ /* STATE check nway, poll until a valid 10/100mbs signal seen */
+ WRITECSR(sc, R_CSR_STATUS, M_CSR5_LINKPASS); /* try to clear this... */
+
+ /* (Re)start negotiation */
+ tempword = READCSR(sc, R_CSR_SIASTATUS);
+ tempword &=~ M_CSR12_AUTONEGARBIT;
+ tempword |= V_CSR12_AUTONEGARBIT(0x1);
+
+ for (count = 0; count <= 13; count++) {
+ tempword = READCSR(sc, R_CSR_STATUS);
+ if (tempword & M_CSR5_LINKPASS)
+ break;
+ cfe_sleep(CFE_HZ/10);
+ }
+
+ if (count > 13)
+ xprintf("%s: Link autonegotiation failed\n", tulip_devname(sc));
+
+ /* STATE configure nway, check to see if any abilities common to us.
+ If they do, set to highest mode, if not, we will see if the partner
+ will do 100mb or 10mb - then set it */
+
+ tempword = READCSR(sc, R_CSR_SIASTATUS);
+ /* clear the autonegogiate complete bit */
+ WRITECSR(sc, R_CSR_STATUS, M_CSR5_LINKPASS);
+
+ if (tempword & M_CSR12_LINKPARTNEG) {
+ /* A link partner was negogiated... */
+
+ xprintf("%s: Link speed: ", tulip_devname(sc));
+ if (tempword & 0x01000000) { /* 100FD */
+ xprintf("100BaseT FDX");
+ linkspeed = ETHER_SPEED_100FDX;
+ }
+ else if (tempword & 0x00800000) { /* 100HD */
+ xprintf("100BaseT HDX");
+ linkspeed = ETHER_SPEED_100HDX;
+ }
+ else if (tempword & 0x00400000) { /* 10FD */
+ xprintf("10BaseT FDX");
+ linkspeed = ETHER_SPEED_10FDX;
+ }
+ else if (tempword & 0x00200000) { /* 10HD */
+ xprintf("10BaseT HDX");
+ linkspeed = ETHER_SPEED_10HDX;
+ }
+ xprintf("\n");
+ }
+ else {
+ /* no link partner negotiation */
+ /* disable link for 1.3 seconds to break any existing connections */
+
+ xprintf("%s: ", tulip_devname(sc));
+ dc21143_set_speed(sc, ETHER_SPEED_10HDX);
+ cfe_sleep(CFE_HZ/8);
+
+ tempword = READCSR(sc, R_CSR_SIASTATUS);
+
+ if ((tempword & 0x02) == 0) {
+ /* 100 mb signal present set to 100mb */
+ xprintf("No link partner... setting to 100BaseT HDX\n");
+ linkspeed = ETHER_SPEED_100HDX;
+ }
+ else if ((tempword & 0x04) == 0) {
+ /* 10 mb signal present */
+ xprintf("No link partner... setting to 10BaseT HDX\n");
+ linkspeed = ETHER_SPEED_10HDX;
+ }
+ else {
+ /* couldn't determine line speed, so set to 10mbs */
+ xprintf("Unknown; defaulting to 10BaseT HDX\n");
+ linkspeed = ETHER_SPEED_10HDX;
+ }
+ }
+
+ dc21143_set_speed(sc, linkspeed);
+}
+
+static void
+dc21143_set_loopback(tulip_softc *sc, int mode)
+{
+ uint32_t v;
+
+ WRITECSR(sc, R_CSR_SIAMODE0, 0);
+ if (mode == ETHER_LOOPBACK_EXT) {
+ /* deal with CSRs 13-15 */
+ }
+ cfe_sleep(CFE_HZ/10); /* check this */
+
+ /* Update the SIA registers */
+ v = READCSR(sc, R_CSR_SIAMODE0);
+ WRITECSR(sc, R_CSR_SIAMODE0, v &~ 0xFFFF);
+ v = READCSR(sc, R_CSR_SIAMODE1);
+ WRITECSR(sc, R_CSR_SIAMODE1, v &~ 0xFFFF);
+ v = READCSR(sc, R_CSR_SIAMODE2);
+ WRITECSR(sc, R_CSR_SIAMODE2, v | 0xC000); /* WC of HCKR, RMP */
+ if (mode == ETHER_LOOPBACK_OFF)
+ WRITECSR(sc, R_CSR_SIAMODE2, sc->gpdata);
+ else
+ WRITECSR(sc, R_CSR_SIAMODE2, (v &~ 0xFFFF) | M_CSR15_GP_AUIBNC);
+
+ WRITECSR(sc, R_CSR_SIAMODE0, M_CSR13_CONN_NOT_RESET);
+
+ sc->loopback = mode;
+}
+
+/* Known vendors with cards requiring special initialization. */
+#define K_PCI_VENDOR_COGENT 0x1109 /* inherited by Adaptec */
+#define K_PCI_VENDOR_PHOBOS 0x13D8
+#define K_PCI_VENDOR_ZNYZ 0x110D
+#define K_PCI_VENDOR_KINGSTON 0x2646
+
+static void
+dc21143_hwinit(tulip_softc *sc, uint8_t srom[])
+{
+ uint32_t v;
+ uint32_t csr6word, csr14word;
+
+ if (SROM_WORD(srom, SROM_VENDOR_INDEX) == K_PCI_VENDOR_COGENT) {
+ /* Cogent/Adaptec MII (ANA-6911A). */
+ sc->phy_type = MII;
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x0821 << 16);
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x0001 << 16);
+ cfe_sleep(CFE_HZ/10);
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x0000 << 16);
+ cfe_sleep(CFE_HZ/2);
+ sc->gpdata = 0;
+ }
+ else if (SROM_WORD(srom, SROM_VENDOR_INDEX) == K_PCI_VENDOR_ZNYZ) {
+ /* Znyz 34xQ adapters */
+ sc->phy_type = SYM;
+
+ /* The ZX345Q with wake-on-LAN enabled apparently clears ANE and
+ TAS on power up (but not cold reset) */
+ WRITECSR(sc, R_CSR_SIAMODE1, 0xFFFFFFFF);
+
+ /* The following is a reset workaround for QS/Kendin PHYs
+ as suggested by an Intel app note. Bit 0x40000 is the PHY
+ reset (low true) on Znyx cards. */
+ WRITECSR(sc, R_CSR_SIAMODE2,
+ M_CSR15_GP_CONTROLWRITE |
+ 0xF0000 | /* all outputs */
+ M_CSR15_GP_LED1 |
+ M_CSR15_GP_AUIBNC);
+ cfe_sleep(CFE_HZ/5);
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x40000); /* release reset */
+ cfe_sleep(CFE_HZ/5);
+ sc->gpdata = 0x40000 | M_CSR15_GP_AUIBNC;
+ }
+ else if (SROM_WORD(srom, SROM_VENDOR_INDEX) == K_PCI_VENDOR_KINGSTON) {
+ /* Kingston KNE100TX */
+ sc->phy_type = MII;
+ sc->gpdata = 0;
+ }
+ else if (SROM_WORD(srom, SROM_VENDOR_INDEX) == K_PCI_VENDOR_PHOBOS) {
+ /* Phobos 430TX quad card */
+ sc->phy_type = MII;
+#if 0 /* per EEPROM */
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x080E << 16);
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x000E << 16);
+ cfe_sleep(CFE_HZ/10);
+ sc->gpdata = 0x0E;
+#else /* following Adaptec 21143 with MII interface */
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x0821 << 16);
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x0001 << 16);
+ cfe_sleep(CFE_HZ/10);
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x0000 << 16);
+ cfe_sleep(CFE_HZ/2);
+ sc->gpdata = 0;
+#endif
+ }
+ else {
+ /* Most 21143 cards use the SYM interface. */
+ sc->phy_type = SYM;
+ WRITECSR(sc, R_CSR_SIAMODE2, M_CSR15_CONFIG_GEPS_LEDS);
+ sc->gpdata = M_CSR15_DEFAULT_VALUE;
+ }
+
+ if (sc->phy_type == MII) {
+ mii_probe(sc);
+ }
+
+ /* CSR0 - bus mode */
+#if TULIP_TUNE
+ v = V_CSR0_SKIPLEN(0) |
+ V_CSR0_CACHEALIGN(K_CSR0_ALIGN32) |
+ M_CSR0_READMULTENAB | M_CSR0_READLINEENAB |
+ M_CSR0_WRITEINVALENAB |
+ V_CSR0_BURSTLEN(K_CSR0_BURST32);
+#else
+ v = V_CSR0_SKIPLEN(0) |
+ V_CSR0_CACHEALIGN(K_CSR0_ALIGN32) |
+ V_CSR0_BURSTLEN(K_CSR0_BURST32);
+#endif
+#ifdef __MIPSEB
+ v |= M_CSR0_BIGENDIAN; /* big-endian data serialization */
+#endif
+ WRITECSR(sc, R_CSR_BUSMODE, v);
+
+ /* CSR6 - operation mode */
+ v = M_CSR6_PORTSEL |
+#if TULIP_TUNE
+ V_CSR6_THRESHCONTROL(K_CSR6_TXTHRES_128_72) |
+#else
+ M_CSR6_STOREFWD |
+#endif
+ M_CSR6_MBO;
+ if (sc->phy_type == SYM)
+ v |= M_CSR6_PCSFUNC |M_CSR6_SCRAMMODE;
+ WRITECSR(sc, R_CSR_OPMODE, v);
+
+ /* About to muck with the SIA, reset it.(?) */
+ /* WRITECSR(sc, R_CSR_SIASTATUS, 0); */
+
+ /* Must shut off all transmit/receive in order to attempt to
+ achieve Full Duplex */
+ csr6word = READCSR(sc, R_CSR_OPMODE);
+ WRITECSR(sc, R_CSR_OPMODE, csr6word &~ (M_CSR6_TXSTART | M_CSR6_RXSTART));
+ csr6word = READCSR(sc, R_CSR_OPMODE);
+
+ WRITECSR(sc, R_CSR_RXRING, PTR_TO_PCI(sc->rxdscr_start));
+ WRITECSR(sc, R_CSR_TXRING, PTR_TO_PCI(sc->txdscr_start));
+
+ if (sc->phy_type == MII) {
+ if (sc->linkspeed == ETHER_SPEED_AUTO)
+ mii_autonegotiate(sc);
+ else
+ mii_set_speed(sc, sc->linkspeed, 0);
+ }
+ else {
+ if (sc->linkspeed == ETHER_SPEED_AUTO) {
+ dc21143_autonegotiate(sc);
+ }
+ else {
+ /* disable autonegotiate so we can set full duplex to on */
+ WRITECSR(sc, R_CSR_SIAMODE0, 0);
+ csr14word = READCSR(sc, R_CSR_SIAMODE1);
+ csr14word &=~ M_CSR14_AUTONEGOTIATE;
+ WRITECSR(sc, R_CSR_SIAMODE1, csr14word);
+ WRITECSR(sc, R_CSR_SIAMODE0, M_CSR13_CONN_NOT_RESET);
+
+ dc21143_set_speed(sc, sc->linkspeed);
+ }
+ }
+}
+
+
+static void
+dc21140_set_speed(tulip_softc *sc, int speed, int autoneg)
+{
+ mii_set_speed(sc, speed, autoneg);
+}
+
+static void
+dc21140_set_loopback(tulip_softc *sc, int mode)
+{
+ if (mode == ETHER_LOOPBACK_EXT) {
+ xprintf("%s: external loopback mode NYI\n", tulip_devname(sc));
+ mode = ETHER_LOOPBACK_OFF;
+ }
+ else if (mode != ETHER_LOOPBACK_INT)
+ mode = ETHER_LOOPBACK_OFF;
+
+ sc->loopback = mode;
+}
+
+static void
+dc21140_hwinit(tulip_softc *sc, uint8_t srom[])
+{
+ uint16_t leaf;
+ uint8_t gpr_control, gpr_data;
+ uint32_t v;
+ uint32_t opmode;
+
+ if (srom[SROM_FORMAT_INDEX] == 0 || srom[SROM_FORMAT_INDEX] > 4) {
+ gpr_control = 0x1F;
+ gpr_data = 0x00;
+ sc->phy_type = MII; /* Most 21140 cards use MII */
+ }
+ else {
+ leaf = SROM_WORD(srom, SROM_LEAF0_OFFSET_INDEX);
+ gpr_control = srom[leaf+2];
+ /* XXX We should parse and check all the leaf info */
+ if ((srom[leaf+4] & 0x80) == 0) {
+ gpr_data = 0x85; /* SYM, 100 Mb/s */
+ sc->phy_type = SYM;
+ }
+ else {
+ gpr_data = 0x00; /* MII */
+ sc->phy_type = MII;
+ }
+ }
+
+ /* Assume that we will use MII or SYM interface */
+ WRITECSR(sc, R_CSR_OPMODE, M_CSR6_PORTSEL);
+ RESET_ADAPTER(sc);
+
+ WRITECSR(sc, R_CSR_GENPORT, M_CSR12_CONTROL | gpr_control);
+ WRITECSR(sc, R_CSR_GENPORT, gpr_data); /* setup PHY */
+
+ if (sc->phy_type == MII) {
+ mii_probe(sc);
+ }
+
+ /* CSR0 - bus mode */
+#if TULIP_TUNE
+ v = V_CSR0_SKIPLEN(0) |
+ V_CSR0_CACHEALIGN(K_CSR0_ALIGN32) |
+ M_CSR0_READMULTENAB | M_CSR0_READLINEENAB |
+ M_CSR0_WRITEINVALENAB |
+ V_CSR0_BURSTLEN(K_CSR0_BURST32);
+#else
+ v = V_CSR0_SKIPLEN(0) |
+ V_CSR0_CACHEALIGN(K_CSR0_ALIGN32) |
+ V_CSR0_BURSTLEN(K_CSR0_BURST32);
+#endif
+#ifdef __MIPSEB
+ v |= M_CSR0_BIGENDIAN; /* big-endian data serialization */
+#endif
+ WRITECSR(sc, R_CSR_BUSMODE, v);
+
+ /* CSR6 - operation mode */
+ v = M_CSR6_PORTSEL |
+#if TULIP_TUNE
+ V_CSR6_THRESHCONTROL(K_CSR6_TXTHRES_128_72) |
+#else
+ M_CSR6_STOREFWD |
+#endif
+ M_CSR6_MBO;
+ WRITECSR(sc, R_CSR_OPMODE, v);
+
+ /* Must shut off all transmit/receive in order to attempt to
+ achieve Full Duplex */
+ opmode = READCSR(sc, R_CSR_OPMODE);
+ WRITECSR(sc, R_CSR_OPMODE, opmode &~ (M_CSR6_TXSTART | M_CSR6_RXSTART));
+ opmode = READCSR(sc, R_CSR_OPMODE);
+
+ WRITECSR(sc, R_CSR_RXRING, PTR_TO_PCI(sc->rxdscr_start));
+ WRITECSR(sc, R_CSR_TXRING, PTR_TO_PCI(sc->txdscr_start));
+
+ if (sc->phy_type == MII) {
+ if (sc->linkspeed == ETHER_SPEED_AUTO)
+ mii_autonegotiate(sc);
+ else
+ mii_set_speed(sc, sc->linkspeed, 0);
+ }
+ else {
+ /* XXX The 21140 requires a soft reset after changing PORTSEL.
+ For now, remain committed to the SYM port (100 Mb/s) */
+ switch (sc->linkspeed) {
+ default:
+ sc->linkspeed = ETHER_SPEED_100HDX; /* for now */
+ /* fall through */
+ case ETHER_SPEED_100HDX:
+ opmode |= M_CSR6_SPEED_100;
+ break;
+ case ETHER_SPEED_100FDX:
+ opmode |= M_CSR6_SPEED_100 | M_CSR6_FULLDUPLEX;
+ break;
+ }
+
+ /* XXX Need to reset and reinitialize if we choose SPEED_10 above */
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+ }
+}
+
+
+static void
+dc21041_set_speed(tulip_softc *sc, int speed)
+{
+ uint32_t opmode = 0;
+
+ WRITECSR(sc, R_CSR_SIAMODE0, 0);
+
+ /* For now, always force 10BT, HDX (21041, Table 3-62) */
+ switch (speed) {
+ case ETHER_SPEED_10HDX:
+ default:
+ WRITECSR(sc, R_CSR_SIAMODE1, 0x7F3F);
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x0008);
+ opmode = M_CSR6_SPEED_10;
+ break;
+ }
+
+ WRITECSR(sc, R_CSR_SIAMODE0, 0xEF00 | M_CSR13_CONN_NOT_RESET);
+ cfe_sleep(CFE_HZ/10);
+
+ opmode |= V_CSR6_THRESHCONTROL(K_CSR6_TXTHRES_128_72);
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+}
+
+static void
+dc21041_set_loopback(tulip_softc *sc, int mode)
+{
+ /* For now, always assume 10BT */
+ uint32_t mode0;
+
+ WRITECSR(sc, R_CSR_SIAMODE0, 0);
+ cfe_sleep(CFE_HZ/10); /* check this */
+
+ /* Update the SIA registers */
+ if (mode == ETHER_LOOPBACK_EXT) {
+ /* NB: this is really just internal but through the 10BT endec */
+ WRITECSR(sc, R_CSR_SIAMODE1, 0x7A3F);
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x0008);
+ mode0 = 0;
+ }
+ else if (mode == ETHER_LOOPBACK_INT) {
+ /* MAC internal loopback, no SIA */
+ WRITECSR(sc, R_CSR_SIAMODE1, 0x0000);
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x000E);
+ mode0 = M_CSR13_CONN_AUI_10BT;
+ }
+ else {
+ mode = ETHER_LOOPBACK_OFF;
+ WRITECSR(sc, R_CSR_SIAMODE1, 0x7F3F);
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x0008);
+ mode0 = 0;
+ }
+
+ WRITECSR(sc, R_CSR_SIAMODE0, 0xEF00 | mode0 | M_CSR13_CONN_NOT_RESET );
+
+ sc->loopback = mode;
+}
+
+static void
+dc21041_hwinit(tulip_softc *sc, uint8_t srom[])
+{
+ uint32_t v;
+
+ sc->phy_type = SRL;
+
+ /* CSR0 - bus mode */
+ v = V_CSR0_SKIPLEN(0) |
+ V_CSR0_CACHEALIGN(K_CSR0_ALIGN32) |
+ V_CSR0_BURSTLEN(K_CSR0_BURST32);
+#ifdef __MIPSEB
+ v |= M_CSR0_BIGENDIAN; /* big-endian data serialization */
+#endif
+ WRITECSR(sc, R_CSR_BUSMODE, v);
+
+ WRITECSR(sc, R_CSR_INTMASK, 0);
+
+ WRITECSR(sc, R_CSR_RXRING, PTR_TO_PCI(sc->rxdscr_start));
+ WRITECSR(sc, R_CSR_TXRING, PTR_TO_PCI(sc->txdscr_start));
+
+ /* For now, always force 10BT, HDX (21041, Table 3-62) */
+ dc21041_set_speed(sc, ETHER_SPEED_10HDX);
+}
+
+
+static void
+dc21040_set_speed(tulip_softc *sc, int speed)
+{
+ uint32_t opmode = 0;
+
+ WRITECSR(sc, R_CSR_SIAMODE0, 0);
+
+ /* For now, force 10BT, HDX unless FDX requested (21040, Table 3-53) */
+ switch (speed) {
+ case ETHER_SPEED_10HDX:
+ default:
+ WRITECSR(sc, R_CSR_SIAMODE1, 0xFFFF);
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x0000);
+ opmode = 0;
+ break;
+ case ETHER_SPEED_10FDX:
+ WRITECSR(sc, R_CSR_SIAMODE1, 0xFFFD);
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x0000);
+ opmode = M_CSR6_FULLDUPLEX;
+ break;
+ }
+
+ WRITECSR(sc, R_CSR_SIAMODE0, 0xEF00 | M_CSR13_CONN_NOT_RESET);
+ cfe_sleep(CFE_HZ/10);
+
+ opmode |= V_CSR6_THRESHCONTROL(K_CSR6_TXTHRES_128_72);
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+}
+
+static void
+dc21040_set_loopback(tulip_softc *sc, int mode)
+{
+ WRITECSR(sc, R_CSR_SIAMODE0, 0);
+ cfe_sleep(CFE_HZ/10); /* check this */
+
+ /* Update the SIA registers */
+ if (mode == ETHER_LOOPBACK_EXT) {
+ /* NB: this is on-chip loopback through the 10BT endec */
+ WRITECSR(sc, R_CSR_SIAMODE1, 0xFEFB);
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x0008);
+ }
+ else if (mode == ETHER_LOOPBACK_INT) {
+ /* MAC internal loopback, no SIA */
+ WRITECSR(sc, R_CSR_SIAMODE1, 0x0000);
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x0000);
+ }
+ else {
+ mode = ETHER_LOOPBACK_OFF;
+ WRITECSR(sc, R_CSR_SIAMODE1, 0xFFFF);
+ WRITECSR(sc, R_CSR_SIAMODE2, 0x0000);
+ }
+
+ WRITECSR(sc, R_CSR_SIAMODE0, 0x8F00 | M_CSR13_CONN_NOT_RESET );
+
+ sc->loopback = mode;
+}
+
+static void
+dc21040_hwinit(tulip_softc *sc, uint8_t srom[])
+{
+ uint32_t v;
+
+ sc->phy_type = SRL;
+
+ /* CSR0 - bus mode */
+ v = V_CSR0_SKIPLEN(0) |
+ V_CSR0_CACHEALIGN(K_CSR0_ALIGN32) |
+ V_CSR0_BURSTLEN(K_CSR0_BURST32);
+#ifdef __MIPSEB
+ v |= M_CSR0_BIGENDIAN; /* big-endian data serialization */
+#endif
+ WRITECSR(sc, R_CSR_BUSMODE, v);
+
+ WRITECSR(sc, R_CSR_INTMASK, 0);
+
+ dc21040_set_speed(sc, sc->linkspeed);
+}
+
+
+static void
+tulip_hwinit(tulip_softc *sc)
+{
+ if (sc->state == eth_state_uninit) {
+ uint8_t srom[SROM_SIZE];
+
+ /* Wake-on-LAN apparently powers up with PORTSEL = 1 */
+ WRITECSR(sc, R_CSR_OPMODE,
+ READCSR(sc, R_CSR_OPMODE) &~ M_CSR6_PORTSEL);
+
+ RESET_ADAPTER(sc);
+ sc->state = eth_state_off;
+ sc->bus_errors = 0;
+
+ rom_read_all(sc, srom); /* XXX read just once? */
+ rom_dump(srom);
+
+ switch (sc->device) {
+ case K_PCI_ID_DC21040:
+ dc21040_hwinit(sc, srom);
+ break;
+ case K_PCI_ID_DC21041:
+ dc21041_hwinit(sc, srom);
+ break;
+ case K_PCI_ID_DC21140:
+ dc21140_hwinit(sc, srom);
+ break;
+ case K_PCI_ID_DC21143:
+ dc21143_hwinit(sc, srom);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void
+tulip_setaddr(tulip_softc *sc)
+{
+ int idx;
+ tulip_cam *cam;
+ eth_pkt_t *pkt;
+
+ pkt = eth_alloc_pkt(sc);
+ if (pkt) {
+ pkt->length = CAM_SETUP_BUFFER_SIZE;
+ cam = (tulip_cam *) pkt->buffer;
+
+#ifdef __MIPSEB
+ cam->p.physical[0][0] = (((uint32_t) sc->hwaddr[0] << 8) |
+ (uint32_t) sc->hwaddr[1]) << 16;
+ cam->p.physical[0][1] = (((uint32_t) sc->hwaddr[2] << 8) |
+ (uint32_t) sc->hwaddr[3]) << 16;
+ cam->p.physical[0][2] = (((uint32_t) sc->hwaddr[4] << 8) |
+ (uint32_t) sc->hwaddr[5]) << 16;
+ for (idx = 1; idx < CAM_PERFECT_ENTRIES; idx++) {
+ cam->p.physical[idx][0] = 0xFFFF0000;
+ cam->p.physical[idx][1] = 0xFFFF0000;
+ cam->p.physical[idx][2] = 0xFFFF0000;
+ }
+#else
+ cam->p.physical[0][0] = ((uint32_t) sc->hwaddr[0]) |
+ (((uint32_t) sc->hwaddr[1]) << 8);
+ cam->p.physical[0][1] = ((uint32_t) sc->hwaddr[2]) |
+ (((uint32_t) sc->hwaddr[3]) << 8);
+ cam->p.physical[0][2] = ((uint32_t) sc->hwaddr[4]) |
+ (((uint32_t) sc->hwaddr[5]) << 8);
+ for (idx = 1; idx < CAM_PERFECT_ENTRIES; idx++) {
+ cam->p.physical[idx][0] = 0x0000FFFF;
+ cam->p.physical[idx][1] = 0x0000FFFF;
+ cam->p.physical[idx][2] = 0x0000FFFF;
+ }
+#endif
+
+ pkt->flags |= ETH_TX_SETUP;
+ sc->state = eth_state_setup;
+ if (tulip_transmit(sc, pkt) != 0) {
+ xprintf("%s: failed setup\n", tulip_devname(sc));
+ dumpstat(sc);
+ eth_free_pkt(sc, pkt);
+ }
+ }
+}
+
+static void
+tulip_setspeed(tulip_softc *sc, int speed)
+{
+ switch (sc->device) {
+ case K_PCI_ID_DC21040:
+ dc21040_set_speed(sc, speed);
+ break;
+ case K_PCI_ID_DC21041:
+ dc21041_set_speed(sc, speed);
+ break;
+ case K_PCI_ID_DC21140:
+ dc21140_set_speed(sc, speed, 0);
+ break;
+ case K_PCI_ID_DC21143:
+ dc21143_set_speed(sc, speed);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+tulip_setloopback(tulip_softc *sc, int mode)
+{
+ switch (sc->device) {
+ case K_PCI_ID_DC21040:
+ dc21040_set_loopback(sc, mode);
+ break;
+ case K_PCI_ID_DC21041:
+ dc21041_set_loopback(sc, mode);
+ break;
+ case K_PCI_ID_DC21140:
+ dc21140_set_loopback(sc, mode);
+ break;
+ case K_PCI_ID_DC21143:
+ dc21143_set_loopback(sc, mode);
+ break;
+ default:
+ break;
+ }
+ cfe_sleep(CFE_HZ/10);
+}
+
+
+static void
+tulip_isr(void *arg)
+{
+ uint32_t status;
+ uint32_t csr5;
+ tulip_softc *sc = (tulip_softc *)arg;
+
+#if IPOLL
+ sc->interrupts++;
+#endif
+
+ for (;;) {
+
+ /* Read the interrupt status. */
+ csr5 = READCSR(sc, R_CSR_STATUS);
+ status = csr5 & (
+ M_CSR5_RXINT | M_CSR5_RXBUFUNAVAIL |
+ M_CSR5_TXINT | M_CSR5_TXUNDERFLOW |
+ M_CSR5_FATALBUSERROR);
+
+ /* if there are no more interrupts, leave now. */
+ if (status == 0) break;
+
+ /* Clear the pending interrupt. */
+ WRITECSR(sc, R_CSR_STATUS, status);
+
+ /* Now, test each unmasked bit in the interrupt register and
+ handle each interrupt type appropriately. */
+
+ if (status & M_CSR5_FATALBUSERROR) {
+ WRITECSR(sc, R_CSR_INTMASK, 0);
+
+ xprintf("%s: bus error %02x\n",
+ tulip_devname(sc), G_CSR5_ERRORBITS(csr5));
+ dumpstat(sc);
+ sc->bus_errors++;
+ if (sc->bus_errors >= 2) {
+ dumpcsrs(sc);
+ RESET_ADAPTER(sc);
+ sc->state = eth_state_off;
+ sc->bus_errors = 0;
+ }
+#if IPOLL
+ else
+ WRITECSR(sc, R_CSR_INTMASK, sc->intmask);
+#endif
+ }
+
+ if (status & M_CSR5_RXINT) {
+#if IPOLL
+ sc->rx_interrupts++;
+#endif
+ tulip_procrxring(sc);
+ }
+
+ if (status & M_CSR5_TXINT) {
+#if IPOLL
+ sc->tx_interrupts++;
+#endif
+ tulip_proctxring(sc);
+ }
+
+ if (status & (M_CSR5_TXUNDERFLOW | M_CSR5_RXBUFUNAVAIL)) {
+ if (status & M_CSR5_TXUNDERFLOW) {
+ xprintf("%s: tx underrun, %08x\n", tulip_devname(sc), csr5);
+ /* Try to restart */
+ WRITECSR(sc, R_CSR_TXPOLL, 1);
+ }
+ if (status & M_CSR5_RXBUFUNAVAIL) {
+ /* Try to restart */
+ WRITECSR(sc, R_CSR_RXPOLL, 1);
+ }
+ }
+ }
+}
+
+
+static void
+tulip_start(tulip_softc *sc)
+{
+ uint32_t opmode;
+
+ tulip_hwinit(sc);
+
+ WRITECSR(sc, R_CSR_RXRING, PTR_TO_PCI(sc->rxdscr_start));
+ WRITECSR(sc, R_CSR_TXRING, PTR_TO_PCI(sc->txdscr_start));
+
+ opmode = READCSR(sc, R_CSR_OPMODE);
+ opmode &=~ M_CSR6_OPMODE; /* no loopback */
+ if (sc->loopback != ETHER_LOOPBACK_OFF) {
+ opmode &=~ M_CSR6_FULLDUPLEX;
+ opmode |= M_CSR6_PORTSEL;
+ if (sc->loopback == ETHER_LOOPBACK_EXT)
+ opmode |= M_CSR6_EXTLOOPBACK;
+ else
+ opmode |= M_CSR6_INTLOOPBACK;
+ }
+
+ sc->intmask = 0;
+ WRITECSR(sc, R_CSR_INTMASK, 0); /* no interrupts */
+ WRITECSR(sc, R_CSR_STATUS, 0x1FFFF); /* clear any pending */
+ READCSR(sc, R_CSR_STATUS); /* push the write */
+
+ sc->interrupts = 0;
+ sc->rx_interrupts = sc->tx_interrupts = 0;
+
+#if IPOLL
+ cfe_request_irq(sc->irq, tulip_isr, sc, CFE_IRQ_FLAGS_SHARED, 0);
+
+ sc->intmask = M_CSR7_RXINT | M_CSR7_TXINT |
+ M_CSR7_NORMALINT;
+ sc->intmask |= M_CSR7_FATALBUSERROR | M_CSR7_TXUNDERFLOW |
+ M_CSR7_ABNORMALINT;
+ WRITECSR(sc, R_CSR_INTMASK, sc->intmask);
+#endif
+
+ if (sc->loopback == ETHER_LOOPBACK_OFF) {
+ opmode |= M_CSR6_TXSTART;
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+ tulip_setaddr(sc);
+ }
+ else {
+ opmode |= M_CSR6_TXSTART | M_CSR6_RXSTART;
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+ }
+}
+
+static void
+tulip_stop(tulip_softc *sc)
+{
+ uint32_t opmode;
+ uint32_t status;
+ int count;
+
+ WRITECSR(sc, R_CSR_INTMASK, 0);
+ sc->intmask = 0;
+#if IPOLL
+ cfe_free_irq(sc->irq, 0);
+#endif
+ WRITECSR(sc, R_CSR_STATUS, 0x1FFFF);
+ opmode = READCSR(sc, R_CSR_OPMODE);
+ opmode &=~ (M_CSR6_TXSTART | M_CSR6_RXSTART);
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+
+ /* wait for any DMA activity to terminate */
+ for (count = 0; count <= 13; count++) {
+ status = READCSR(sc, R_CSR_STATUS);
+ if ((status & (M_CSR5_RXPROCSTATE | M_CSR5_TXPROCSTATE)) == 0)
+ break;
+ cfe_sleep(CFE_HZ/10);
+ }
+ if (count > 13) {
+ xprintf("%s: idle state not achieved\n", tulip_devname(sc));
+ dumpstat(sc);
+ RESET_ADAPTER(sc);
+ sc->state = eth_state_uninit;
+#if 1
+ sc->linkspeed = ETHER_SPEED_AUTO;
+#endif
+ }
+ else if (sc->loopback != ETHER_LOOPBACK_OFF) {
+ tulip_setloopback(sc, ETHER_LOOPBACK_OFF);
+ opmode &=~ M_CSR6_OPMODE;
+ WRITECSR(sc, R_CSR_OPMODE, opmode);
+ }
+
+ if (sc->outpkts > 1) {
+ /* heuristic: suppress stats for initial mode changes */
+ xprintf("%s: %d sent, %d received, %d interrupts\n",
+ tulip_devname(sc), sc->outpkts, sc->inpkts, sc->interrupts);
+ xprintf(" %d rx interrupts, %d tx interrupts\n",
+ sc->rx_interrupts, sc->tx_interrupts);
+ }
+}
+
+
+/* *********************************************************************
+ * ETH_PARSE_XDIGIT(c)
+ *
+ * Parse a hex digit, returning its value
+ *
+ * Input parameters:
+ * c - character
+ *
+ * Return value:
+ * hex value, or -1 if invalid
+ ********************************************************************* */
+static int
+eth_parse_xdigit(char c)
+{
+ int digit;
+
+ if ((c >= '0') && (c <= '9')) digit = c - '0';
+ else if ((c >= 'a') && (c <= 'f')) digit = c - 'a' + 10;
+ else if ((c >= 'A') && (c <= 'F')) digit = c - 'A' + 10;
+ else digit = -1;
+
+ return digit;
+}
+
+/* *********************************************************************
+ * ETH_PARSE_HWADDR(str,hwaddr)
+ *
+ * Convert a string in the form xx:xx:xx:xx:xx:xx into a 6-byte
+ * Ethernet address.
+ *
+ * Input parameters:
+ * str - string
+ * hwaddr - pointer to hardware address
+ *
+ * Return value:
+ * 0 if ok, else -1
+ ********************************************************************* */
+static int
+eth_parse_hwaddr(char *str, uint8_t *hwaddr)
+{
+ int digit1, digit2;
+ int idx = ENET_ADDR_LEN;
+
+ while (*str && (idx > 0)) {
+ digit1 = eth_parse_xdigit(*str);
+ if (digit1 < 0) return -1;
+ str++;
+ if (!*str) return -1;
+
+ if ((*str == ':') || (*str == '-')) {
+ digit2 = digit1;
+ digit1 = 0;
+ }
+ else {
+ digit2 = eth_parse_xdigit(*str);
+ if (digit2 < 0) return -1;
+ str++;
+ }
+
+ *hwaddr++ = (digit1 << 4) | digit2;
+ idx--;
+
+ if ((*str == ':') || (*str == '-'))
+ str++;
+ }
+ return 0;
+}
+
+/* *********************************************************************
+ * ETH_INCR_HWADDR(hwaddr,incr)
+ *
+ * Increment a 6-byte Ethernet hardware address, with carries
+ *
+ * Input parameters:
+ * hwaddr - pointer to hardware address
+ * incr - desired increment
+ *
+ * Return value:
+ * none
+ ********************************************************************* */
+static void
+eth_incr_hwaddr(uint8_t *hwaddr, unsigned incr)
+{
+ int idx;
+ int carry;
+
+ idx = 5;
+ carry = incr;
+ while (idx >= 0 && carry != 0) {
+ unsigned sum = hwaddr[idx] + carry;
+
+ hwaddr[idx] = sum & 0xFF;
+ carry = sum >> 8;
+ idx--;
+ }
+}
+
+
+/* *********************************************************************
+ * Declarations for CFE Device Driver Interface routines
+ ********************************************************************* */
+
+static int tulip_ether_open(cfe_devctx_t *ctx);
+static int tulip_ether_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int tulip_ether_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int tulip_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int tulip_ether_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int tulip_ether_close(cfe_devctx_t *ctx);
+#if 0
+static void tulip_ether_reset(void *softc);
+#endif
+
+/* *********************************************************************
+ * CFE Device Driver dispatch structure
+ ********************************************************************* */
+
+const static cfe_devdisp_t tulip_ether_dispatch = {
+ tulip_ether_open,
+ tulip_ether_read,
+ tulip_ether_inpstat,
+ tulip_ether_write,
+ tulip_ether_ioctl,
+ tulip_ether_close,
+ NULL, /* tulip_ether_poll */
+ NULL /* tulip_ether_reset */
+};
+
+/* *********************************************************************
+ * CFE Device Driver descriptor
+ ********************************************************************* */
+
+const cfe_driver_t dc21143drv = {
+ "DC21x4x Ethernet",
+ "eth",
+ CFE_DEV_NETWORK,
+ &tulip_ether_dispatch,
+ tulip_ether_probe
+};
+
+
+static int
+tulip_ether_attach(cfe_driver_t *drv,
+ pcitag_t tag, int index, uint8_t hwaddr[])
+{
+ tulip_softc *softc;
+ uint32_t device;
+ uint32_t class;
+ uint32_t reg;
+ phys_addr_t pa;
+ const char *devname;
+ char descr[100];
+ uint8_t romaddr[ENET_ADDR_LEN];
+
+ device = pci_conf_read(tag, R_CFG_CFID);
+ class = pci_conf_read(tag, R_CFG_CFRV);
+
+ reg = pci_conf_read(tag, R_CFG_CPMS);
+
+ reg = pci_conf_read(tag, R_CFG_CFDD);
+ pci_conf_write(tag, R_CFG_CFDD, 0);
+ reg = pci_conf_read(tag, R_CFG_CFDD);
+
+#if 1
+ /* Use memory space for the CSRs */
+ pci_map_mem(tag, R_CFG_CBMA, PCI_MATCH_BITS, &pa);
+#else
+ /* Use i/o space for the CSRs */
+ pci_map_io(tag, R_CFG_CBIO, PCI_MATCH_BITS, &pa);
+#endif
+
+ softc = (tulip_softc *) KMALLOC(sizeof(tulip_softc), 0);
+ if (softc == NULL) {
+ xprintf("DC21x4x: No memory to complete probe\n");
+ return 0;
+ }
+ memset(softc, 0, sizeof(*softc));
+
+ softc->membase = (uint32_t)pa;
+ softc->irq = pci_conf_read(tag, R_CFG_CFIT) & 0xFF;
+
+ softc->tag = tag;
+ softc->device = PCI_PRODUCT(device);
+ softc->revision = PCI_REVISION(class);
+ softc->devctx = NULL;
+
+#if 1
+ softc->linkspeed = ETHER_SPEED_AUTO; /* select autonegotiation */
+#else
+ softc->linkspeed = ETHER_SPEED_100FDX; /* 100 Mbps, full duplex */
+#endif
+ softc->loopback = ETHER_LOOPBACK_OFF;
+ memcpy(softc->hwaddr, hwaddr, ENET_ADDR_LEN);
+
+ tulip_init(softc);
+
+ /* Prefer address in srom */
+ if (rom_read_addr(softc, romaddr) == 0) {
+ memcpy(softc->hwaddr, romaddr, ENET_ADDR_LEN);
+ }
+
+ softc->state = eth_state_uninit;
+
+ switch (PCI_PRODUCT(device)) {
+ case K_PCI_ID_DC21040:
+ devname = "DC21040"; break;
+ case K_PCI_ID_DC21041:
+ devname = "DC21041"; break;
+ case K_PCI_ID_DC21140:
+ devname = "DC21140"; break;
+ case K_PCI_ID_DC21143:
+ devname = "DC21143"; break;
+ default:
+ devname = "DC21x4x"; break;
+ }
+
+ xsprintf(descr, "%s Ethernet at 0x%X (%02X-%02X-%02X-%02X-%02X-%02X)",
+ devname, softc->membase,
+ softc->hwaddr[0], softc->hwaddr[1], softc->hwaddr[2],
+ softc->hwaddr[3], softc->hwaddr[4], softc->hwaddr[5]);
+
+ cfe_attach(drv, softc, NULL, descr);
+ return 1;
+}
+
+
+/* *********************************************************************
+ * TULIP_ETHER_PROBE(drv,probe_a,probe_b,probe_ptr)
+ *
+ * Probe and install drivers for all DC21x4x Ethernet controllers.
+ * For each, create a context structure and attach to the
+ * specified network device.
+ *
+ * Input parameters:
+ * drv - driver descriptor
+ * probe_a - not used
+ * probe_b - not used
+ * probe_ptr - string pointer to hardware address for the first
+ * MAC, in the form xx:xx:xx:xx:xx:xx
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void
+tulip_ether_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ int index;
+ int n;
+ uint8_t hwaddr[ENET_ADDR_LEN];
+
+ if (probe_ptr)
+ eth_parse_hwaddr((char *) probe_ptr, hwaddr);
+ else {
+ /* use default address 40-00-00-10-11-11 */
+ hwaddr[0] = 0x40; hwaddr[1] = 0x00; hwaddr[2] = 0x00;
+ hwaddr[3] = 0x10; hwaddr[4] = 0x11; hwaddr[5] = 0x11;
+ }
+
+ n = 0;
+ index = 0;
+ for (;;) {
+ pcitag_t tag;
+ pcireg_t device;
+
+ if (pci_find_class(PCI_CLASS_NETWORK, index, &tag) != 0)
+ break;
+
+ index++;
+
+ device = pci_conf_read(tag, R_CFG_CFID);
+ if (PCI_VENDOR(device) == K_PCI_VENDOR_DEC) {
+#if 0 /* this currently (2.1.1) generates a bad code in PIC mode */
+ switch (PCI_PRODUCT(device)) {
+ case K_PCI_ID_DC21040:
+ case K_PCI_ID_DC21041:
+ case K_PCI_ID_DC21140:
+ case K_PCI_ID_DC21143:
+ tulip_ether_attach(drv, tag, n, hwaddr);
+ n++;
+ eth_incr_hwaddr(hwaddr, 1);
+ break;
+ default:
+ break;
+ }
+#else
+ if (PCI_PRODUCT(device) == K_PCI_ID_DC21040 ||
+ PCI_PRODUCT(device) == K_PCI_ID_DC21041 ||
+ PCI_PRODUCT(device) == K_PCI_ID_DC21140 ||
+ PCI_PRODUCT(device) == K_PCI_ID_DC21143) {
+
+ tulip_ether_attach(drv, tag, n, hwaddr);
+ n++;
+ eth_incr_hwaddr(hwaddr, 1);
+ }
+#endif
+ }
+ }
+}
+
+
+/* The functions below are called via the dispatch vector for the 21x4x. */
+
+/* *********************************************************************
+ * TULIP_ETHER_OPEN(ctx)
+ *
+ * Open the Ethernet device. The MAC is reset, initialized, and
+ * prepared to receive and send packets.
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+tulip_ether_open(cfe_devctx_t *ctx)
+{
+ tulip_softc *softc = ctx->dev_softc;
+
+ if (softc->state == eth_state_on)
+ tulip_stop(softc);
+
+ softc->devctx = ctx;
+ tulip_start(softc);
+
+#if XPOLL
+ tulip_isr(softc);
+#endif
+
+ return 0;
+}
+
+/* *********************************************************************
+ * TULIP_ETHER_READ(ctx,buffer)
+ *
+ * Read a packet from the Ethernet device. If no packets are
+ * available, the read will succeed but return 0 bytes.
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ * buffer - pointer to buffer descriptor.
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+tulip_ether_read(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ tulip_softc *softc = ctx->dev_softc;
+ eth_pkt_t *pkt;
+ int blen;
+
+#if XPOLL
+ tulip_isr(softc);
+#endif
+
+ if (softc->state != eth_state_on) return -1;
+
+ CS_ENTER(softc);
+ pkt = (eth_pkt_t *) q_deqnext(&(softc->rxqueue));
+ CS_EXIT(softc);
+
+ if (pkt == NULL) {
+ buffer->buf_retlen = 0;
+ return 0;
+ }
+
+ blen = buffer->buf_length;
+ if (blen > pkt->length) blen = pkt->length;
+
+ blockcopy(buffer->buf_ptr, pkt->buffer, blen);
+ buffer->buf_retlen = blen;
+
+ eth_free_pkt(softc, pkt);
+ tulip_fillrxring(softc);
+
+#if XPOLL
+ tulip_isr(softc);
+#endif
+
+ return 0;
+}
+
+/* *********************************************************************
+ * TULIP_ETHER_INPSTAT(ctx,inpstat)
+ *
+ * Check for received packets on the Ethernet device
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ * inpstat - pointer to input status structure
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+tulip_ether_inpstat(cfe_devctx_t *ctx, iocb_inpstat_t *inpstat)
+{
+ tulip_softc *softc = ctx->dev_softc;
+
+#if XPOLL
+ tulip_isr(softc);
+#endif
+
+ if (softc->state != eth_state_on) return -1;
+
+ /* We avoid an interlock here because the result is a hint and an
+ interrupt cannot turn a non-empty queue into an empty one. */
+ inpstat->inp_status = (q_isempty(&(softc->rxqueue))) ? 0 : 1;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * TULIP_ETHER_WRITE(ctx,buffer)
+ *
+ * Write a packet to the Ethernet device.
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ * buffer - pointer to buffer descriptor.
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+tulip_ether_write(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ tulip_softc *softc = ctx->dev_softc;
+ eth_pkt_t *pkt;
+ int blen;
+
+#if XPOLL
+ tulip_isr(softc);
+#endif
+
+ if (softc->state != eth_state_on) return -1;
+
+ pkt = eth_alloc_pkt(softc);
+ if (!pkt) return CFE_ERR_NOMEM;
+
+ blen = buffer->buf_length;
+ if (blen > pkt->length) blen = pkt->length;
+
+ blockcopy(pkt->buffer, buffer->buf_ptr, blen);
+ pkt->length = blen;
+
+ if (tulip_transmit(softc, pkt) != 0) {
+ eth_free_pkt(softc,pkt);
+ return CFE_ERR_IOERR;
+ }
+
+#if XPOLL
+ tulip_isr(softc);
+#endif
+
+ return 0;
+}
+
+/* *********************************************************************
+ * TULIP_ETHER_IOCTL(ctx,buffer)
+ *
+ * Do device-specific I/O control operations for the device
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ * buffer - pointer to buffer descriptor.
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+tulip_ether_ioctl(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ tulip_softc *softc = ctx->dev_softc;
+ int *argp;
+ int mode;
+ int speed;
+
+ switch ((int)buffer->buf_ioctlcmd) {
+ case IOCTL_ETHER_GETHWADDR:
+ memcpy(buffer->buf_ptr, softc->hwaddr, sizeof(softc->hwaddr));
+ return 0;
+
+ case IOCTL_ETHER_SETHWADDR:
+ return -1; /* not supported */
+
+ case IOCTL_ETHER_GETSPEED:
+ argp = (int *) buffer->buf_ptr;
+ *argp = softc->linkspeed;
+ return 0;
+
+ case IOCTL_ETHER_SETSPEED:
+ tulip_stop(softc);
+ tulip_resetrings(softc);
+ speed = *((int *) buffer->buf_ptr);
+ tulip_setspeed(softc, speed);
+ tulip_start(softc);
+ softc->state = eth_state_on;
+ return 0;
+
+ case IOCTL_ETHER_GETLINK:
+ argp = (int *) buffer->buf_ptr;
+ *argp = softc->linkspeed;
+ return 0;
+
+ case IOCTL_ETHER_GETLOOPBACK:
+ *((int *) buffer) = softc->loopback;
+ return 0;
+
+ case IOCTL_ETHER_SETLOOPBACK:
+ tulip_stop(softc);
+ tulip_resetrings(softc);
+ mode = *((int *) buffer->buf_ptr);
+ softc->loopback = ETHER_LOOPBACK_OFF; /* default */
+ if (mode == ETHER_LOOPBACK_INT || mode == ETHER_LOOPBACK_EXT) {
+ tulip_setloopback(softc, mode);
+ }
+ tulip_start(softc);
+ softc->state = eth_state_on;
+ return 0;
+
+ default:
+ return -1;
+ }
+}
+
+/* *********************************************************************
+ * TULIP_ETHER_CLOSE(ctx)
+ *
+ * Close the Ethernet device.
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ *
+ * Return value:
+ * status, 0 = ok
+ ********************************************************************* */
+static int
+tulip_ether_close(cfe_devctx_t *ctx)
+{
+ tulip_softc *softc = ctx->dev_softc;
+
+ softc->state = eth_state_off;
+ tulip_stop(softc);
+
+ /* resynchronize descriptor rings */
+ tulip_resetrings(softc);
+
+ softc->devctx = NULL;
+ return 0;
+}
+
+
+#if 0
+/* *********************************************************************
+ * TULIP_ETHER_POLL(ctx,ticks)
+ *
+ * TBD
+ *
+ * Input parameters:
+ * ctx - device context (includes ptr to our softc)
+ * ticks- current time in ticks
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void
+tulip_ether_poll(cfe_devctx_t *ctx, int64_t ticks)
+{
+}
+
+/* *********************************************************************
+ * TULIP_ETHER_RESET(softc)
+ *
+ * This routine is called when CFE is restarted after a
+ * program exits. We can clean up pending I/Os here.
+ *
+ * Input parameters:
+ * softc - pointer to tulip_softc
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void
+tulip_ether_reset(void *softc)
+{
+ tulip_softc *sc = (tulip_softc *)softc;
+
+ /* Turn off the Ethernet interface. */
+
+ RESET_ADAPTER(sc);
+}
+#endif
diff --git a/cfe/cfe/dev/dp83815.h b/cfe/cfe/dev/dp83815.h
new file mode 100644
index 0000000..1d50422
--- /dev/null
+++ b/cfe/cfe/dev/dp83815.h
@@ -0,0 +1,559 @@
+/*
+ * Register and bit definitions for the National Semiconductor
+ * DP83815 10/100 Integrated Ethernet MAC and PHY.
+ * Reference:
+ * DP83815 10/100 Mb/s Integrated PCI Ethernet Media Access
+ * Controller and Physical Layer (MacPhyter)
+ * Hardware Reference Manual, Revision 1.0.
+ * National Semiconductor Corp., December 2000
+ */
+#ifndef _DP83815_H_
+#define _DP83815_H_
+
+#define _DD_MAKEMASK1(n) (1 << (n))
+#define _DD_MAKEMASK(v,n) ((((1)<<(v))-1) << (n))
+#define _DD_MAKEVALUE(v,n) ((v) << (n))
+#define _DD_GETVALUE(v,n,m) (((v) & (m)) >> (n))
+
+
+/* PCI Configuration Register offsets (MacPhyter nomenclature) */
+
+#define R_CFGID PCI_ID_REG
+#define K_PCI_VENDOR_NSC 0x100B
+#define K_PCI_ID_DP83815 0x0020
+
+#define R_CFGCS PCI_COMMAND_STATUS_REG
+#define R_CFGRID PCI_CLASS_REG
+#define R_CFGLAT PCI_BHLC_REG
+
+#define R_CFGIOA PCI_MAPREG(0)
+#define R_CFGMA PCI_MAPREG(1)
+
+#define R_CFGSID PCI_SUBSYS_ID_REG
+#define R_CFGROM PCI_MAPREG_ROM
+#define R_CAPPTR PCI_CAPLISTPTR_REG
+#define R_CFGINT PCI_BPARAM_INTERRUPT_REG
+
+/* Power management capability */
+#define R_PMCAP 0x40
+#define R_PMCSR 0x44
+
+
+/* MacPhyter Operational Register offsets */
+
+#define R_CR 0x00
+#define R_CFG 0x04
+#define R_MEAR 0x08
+#define R_PTSCR 0x0C
+#define R_ISR 0x10
+#define R_IMR 0x14
+#define R_IER 0x18
+#define R_TXDP 0x20
+#define R_TXCFG 0x24
+#define R_RXDP 0x30
+#define R_RXCFG 0x34
+#define R_CCSR 0x3C
+#define R_WCSR 0x40
+#define R_PCR 0x44
+#define R_RFCR 0x48
+#define R_RFDR 0x4C
+#define R_BRAR 0x50
+#define R_BRDR 0x54
+#define R_SRR 0x58
+#define R_MIBC 0x5C
+#define R_MIB(n) (0x60+4*(n))
+
+/* MacPhyter MIB Registers */
+
+#define R_MIB_RXErroredPkts R_MIB(0)
+#define R_MIB_RXFCSErrors R_MIB(1)
+#define R_MIB_RXMsdPktErrors R_MIB(2)
+#define R_MIB_RXFAErrors R_MIB(3)
+#define R_MIB_RXSymbolErrors R_MIB(4)
+#define R_MIB_RXFrameTooLong R_MIB(5)
+#define R_MIB_TXSQEErrors R_MIB(6)
+
+#define N_MIB_REGISTERS 7
+
+
+/* MacPhyter Internal PHY Register offsets */
+
+#define R_BMCR 0x80
+#define R_BMSR 0x84
+#define R_PHYIDR1 0x88
+#define R_PHYIDR2 0x8C
+#define R_ANAR 0x90
+#define R_ANLPAR 0x94
+#define R_ANER 0x98
+#define R_ANNPTR 0x9C
+#define R_PHYSTS 0xC0
+#define R_MICR 0xC4
+#define R_MISR 0xC8
+#define R_FCSCR 0xD0
+#define R_RECR 0xD4
+#define R_PHYCR 0xE4
+#define R_TBTSCR 0xE8
+
+/* Undocumented, updated for CVNG (SRR=0x0302) parts */
+
+#define R_PGSEL 0xCC
+#define R_PMDCSR 0xE4 /* R_PHYCR */
+#define R_DSPCFG 0xF4
+#define R_SDCFG 0xF8
+#define R_TSTDAT 0xFC
+
+
+/* 0x00 CR: Command Register */
+
+#define M_CR_TXE _DD_MAKEMASK1(0)
+#define M_CR_TXD _DD_MAKEMASK1(1)
+#define M_CR_RXE _DD_MAKEMASK1(2)
+#define M_CR_RXD _DD_MAKEMASK1(3)
+#define M_CR_TXR _DD_MAKEMASK1(4)
+#define M_CR_RXR _DD_MAKEMASK1(5)
+#define M_CR_SWI _DD_MAKEMASK1(7)
+#define M_CR_RST _DD_MAKEMASK1(8)
+
+
+/* 0x04 CFG: Configuration and Media Status Register */
+
+#define M_CFG_BEM _DD_MAKEMASK1(0)
+#define M_CFG_BROM_DIS _DD_MAKEMASK1(2)
+#define M_CFG_PESEL _DD_MAKEMASK1(3)
+#define M_CFG_EXD _DD_MAKEMASK1(4)
+#define M_CFG_POW _DD_MAKEMASK1(5)
+#define M_CFG_SB _DD_MAKEMASK1(6)
+#define M_CFG_REQALG _DD_MAKEMASK1(7)
+#define M_CFG_EUPHCOMP _DD_MAKEMASK1(8)
+#define M_CFG_PHY_DIS _DD_MAKEMASK1(9)
+#define M_CFG_PHY_RST _DD_MAKEMASK1(10)
+#define M_CFG_EXT_PHY _DD_MAKEMASK1(12)
+
+#define S_CFG_ANEG_SEL 13
+#define M_CFG_ANEG_SEL _DD_MAKEMASK(3,S_CFG_ANEG_SEL)
+#define V_CFG_ANEG_SEL(x) _DD_MAKEVALUE(x,S_CFG_ANEG_SEL)
+#define G_CFG_ANEG_SEL(x) _DD_GETVALUE(x,S_CFG_ANEG_SEL,M_CFG_ANEG_SEL)
+
+#define K_ANEG_10H 0x0
+#define K_ANEG_100H 0x2
+#define K_ANEG_10F 0x4
+#define K_ANEG_100F 0x6
+#define K_ANEG_10HF 0x1
+#define K_ANEG_10H_100H 0x3
+#define K_ANEG_100HF 0x5
+#define K_ANEG_10HF_100HF 0x7
+#define K_ANEG_ALL 0x7
+
+#define M_CFG_PAUSE_ADV _DD_MAKEMASK1(16)
+#define M_CFG_PINT_ACEN _DD_MAKEMASK1(17)
+
+#define S_CFG_PHY_CFG 18
+#define M_CFG_PHY_CFG _DD_MAKEMASK(6,S_CFG_PHY_CFG)
+
+#define M_CFG_ANEG_DN _DD_MAKEMASK1(27)
+#define M_CFG_POL _DD_MAKEMASK1(28)
+#define M_CFG_FDUP _DD_MAKEMASK1(29)
+#define M_CFG_SPEED100 _DD_MAKEMASK1(30)
+#define M_CFG_LNKSTS _DD_MAKEMASK1(31)
+#define M_CFG_LNKSUMMARY (M_CFG_LNKSTS | M_CFG_SPEED100 | M_CFG_FDUP)
+
+
+/* 0x08 MEAR: EEPROM Access Register (see 4.2.4 for EEPROM Map) */
+
+#define M_MEAR_EEDI _DD_MAKEMASK1(0)
+#define M_MEAR_EEDO _DD_MAKEMASK1(1)
+#define M_MEAR_EECLK _DD_MAKEMASK1(2)
+#define M_MEAR_EESEL _DD_MAKEMASK1(3)
+#define M_MEAR_MDIO _DD_MAKEMASK1(4)
+#define M_MEAR_MDDIR _DD_MAKEMASK1(5)
+#define M_MEAR_MDC _DD_MAKEMASK1(6)
+
+
+/* 0x0C PTSCR: PCI Test Control Register */
+
+#define M_PTSCR_EEBIST_FAIL _DD_MAKEMASK1(0)
+#define M_PTSCR_EEBIST_EN _DD_MAKEMASK1(1)
+#define M_PTSCR_EELOAD_EN _DD_MAKEMASK1(2)
+#define M_PTSCR_RBIST_RXFFAIL _DD_MAKEMASK1(3)
+#define M_PTSCR_RBIST_TXFAIL _DD_MAKEMASK1(4)
+#define M_PTSCR_RBIST_RXFAIL _DD_MAKEMASK1(5)
+#define M_PTSCR_RBIST_DONE _DD_MAKEMASK1(6)
+#define M_PTSCR_RBIST_EN _DD_MAKEMASK1(7)
+#define M_PTSCR_MBZ8 _DD_MAKEMASK1(8)
+#define M_PTSCR_MBZ9 _DD_MAKEMASK1(9)
+#define M_PTSCR_RBIST_RST _DD_MAKEMASK1(10)
+#define M_PTSCR_MBZ12 _DD_MAKEMASK1(12)
+
+
+/* 0x10 ISR: Interrupt Status Register */
+/* 0x14 IMR: Interrupt Mask Register */
+
+#define M_INT_RXOK _DD_MAKEMASK1(0)
+#define M_INT_RXDESC _DD_MAKEMASK1(1)
+#define M_INT_RXERR _DD_MAKEMASK1(2)
+#define M_INT_RXEARLY _DD_MAKEMASK1(3)
+#define M_INT_RXIDLE _DD_MAKEMASK1(4)
+#define M_INT_RXORN _DD_MAKEMASK1(5)
+#define M_INT_TXOK _DD_MAKEMASK1(6)
+#define M_INT_TXDESC _DD_MAKEMASK1(7)
+#define M_INT_TXERR _DD_MAKEMASK1(8)
+#define M_INT_TXIDLE _DD_MAKEMASK1(9)
+#define M_INT_TXURN _DD_MAKEMASK1(10)
+#define M_INT_MIB _DD_MAKEMASK1(11)
+#define M_INT_SWI _DD_MAKEMASK1(12)
+#define M_INT_PME _DD_MAKEMASK1(13)
+#define M_INT_PHY _DD_MAKEMASK1(14)
+#define M_INT_HIBERR _DD_MAKEMASK1(15)
+#define M_INT_RXSOVR _DD_MAKEMASK1(16)
+#define M_INT_RTABT _DD_MAKEMASK1(20)
+#define M_INT_RMABT _DD_MAKEMASK1(21)
+#define M_INT_SSERR _DD_MAKEMASK1(22)
+#define M_INT_DPERR _DD_MAKEMASK1(23)
+#define M_INT_RXRCMP _DD_MAKEMASK1(24)
+#define M_INT_TXRCMP _DD_MAKEMASK1(25)
+
+
+/* 0x18 IER: Interrupt Enable Register */
+
+#define M_IER_IE _DD_MAKEMASK1(0)
+
+
+/* 0x20 TXDP: Transmit Descriptor Pointer Register */
+
+
+/* 0x24 TXCFG: Transmit Configuration Register */
+
+#define S_TXCFG_DRTH 0
+#define M_TXCFG_DRTH _DD_MAKEMASK(6,S_TXCFG_DRTH)
+#define V_TXCFG_DRTH(x) _DD_MAKEVALUE(x,S_TXCFG_DRTH)
+#define G_TXCFG_DRTH(x) _DD_GETVALUE(x,S_TXCFG_DRTH,M_TXCFG_DRTH)
+
+#define S_TXCFG_FLTH 8
+#define M_TXCFG_FLTH _DD_MAKEMASK(6,S_TXCFG_FLTH)
+#define V_TXCFG_FLTH(x) _DD_MAKEVALUE(x,S_TXCFG_FLTH)
+#define G_TXCFG_FLTH(x) _DD_GETVALUE(x,S_TXCFG_FLTH,M_TXCFG_FLTH)
+
+#define S_TXCFG_MXDMA 20
+#define M_TXCFG_MXDMA _DD_MAKEMASK(3,S_TXCFG_MXDMA)
+#define V_TXCFG_MXDMA(x) _DD_MAKEVALUE(x,S_TXCFG_MXDMA)
+#define G_TXCFG_MXDMA(x) _DD_GETVALUE(x,S_TXCFG_MXDMA,M_TXCFG_MXDMA)
+
+/* Max DMA burst size (bytes) - RX also */
+#define K_MXDMA_512 0x0
+#define K_MXDMA_4 0x1
+#define K_MXDMA_8 0x2
+#define K_MXDMA_16 0x3
+#define K_MXDMA_32 0x4
+#define K_MXDMA_64 0x5
+#define K_MXDMA_128 0x6
+#define K_MXDMA_256 0x7
+
+#define M_TXCFG_ECRETRY _DD_MAKEMASK1(23)
+
+#define S_TXCFG_IFG 26
+#define M_TXCFG_IFG _DD_MAKEMASK(2,S_TXCFG_IFG)
+#define V_TXCFG_IFG(x) _DD_MAKEVALUE(x,S_TXCFG_IFG)
+#define G_TXCFG_IFG(x) _DD_GETVALUE(x,S_TXCFG_IFG,M_TXCFG_IFG)
+
+#define M_TXCFG_ATP _DD_MAKEMASK1(28)
+#define M_TXCFG_MLB _DD_MAKEMASK1(29)
+#define M_TXCFG_HBI _DD_MAKEMASK1(30)
+#define M_TXCFG_CSI _DD_MAKEMASK1(31)
+
+
+/* 0x30 RXDP: Receive Descriptor Pointer Register */
+
+
+/* 0x34 RXCFG: Receive Configuration Register */
+
+#define S_RXCFG_DRTH 1
+#define M_RXCFG_DRTH _DD_MAKEMASK(5,S_RXCFG_DRTH)
+#define V_RXCFG_DRTH(x) _DD_MAKEVALUE(x,S_RXCFG_DRTH)
+#define G_RXCFG_DRTH(x) _DD_GETVALUE(x,S_RXCFG_DRTH,M_RXCFG_DRTH)
+
+#define S_RXCFG_MXDMA 20
+#define M_RXCFG_MXDMA _DD_MAKEMASK(3,S_RXCFG_MXDMA)
+#define V_RXCFG_MXDMA(x) _DD_MAKEVALUE(x,S_RXCFG_MXDMA)
+#define G_RXCFG_MXDMA(x) _DD_GETVALUE(x,S_RXCFG_MXDMA,M_RXCFG_MXDMA)
+
+#define M_RXCFG_ALP _DD_MAKEMASK1(27)
+#define M_RXCFG_ATX _DD_MAKEMASK1(28)
+#define M_RXCFG_ARP _DD_MAKEMASK1(30)
+#define M_RXCFG_AEP _DD_MAKEMASK1(31)
+
+
+/* 0x3C CCSR: CLKRUN Control/Status Register */
+
+#define M_CCSR_CLKRUN_EN _DD_MAKEMASK1(0)
+#define M_CCSR_PMEEN _DD_MAKEMASK1(8)
+#define M_CCSR_PMESTS _DD_MAKEMASK1(15)
+
+
+/* 0x40 WCSR: Wake Command/Status Register */
+
+#define M_WCSR_WKPHY _DD_MAKEMASK1(0)
+#define M_WCSR_WKUCP _DD_MAKEMASK1(1)
+#define M_WCSR_WKMCP _DD_MAKEMASK1(2)
+#define M_WCSR_WKBCP _DD_MAKEMASK1(3)
+#define M_WCSR_WKARP _DD_MAKEMASK1(4)
+#define M_WCSR_WKPAT0 _DD_MAKEMASK1(5)
+#define M_WCSR_WKPAT1 _DD_MAKEMASK1(6)
+#define M_WCSR_WKPAT2 _DD_MAKEMASK1(7)
+#define M_WCSR_WKPAT3 _DD_MAKEMASK1(8)
+#define M_WCSR_WKMAG _DD_MAKEMASK1(9)
+#define M_WCSR_MPSOE _DD_MAKEMASK1(10)
+#define M_WCSR_SOHACK _DD_MAKEMASK1(20)
+#define M_WCSR_PHYINT _DD_MAKEMASK1(22)
+#define M_WCSR_UCASTR _DD_MAKEMASK1(23)
+#define M_WCSR_MCASTR _DD_MAKEMASK1(24)
+#define M_WCSR_BCASTR _DD_MAKEMASK1(25)
+#define M_WCSR_ARPR _DD_MAKEMASK1(26)
+#define M_WCSR_PATM0 _DD_MAKEMASK1(27)
+#define M_WCSR_PATM1 _DD_MAKEMASK1(28)
+#define M_WCSR_PATM2 _DD_MAKEMASK1(29)
+#define M_WCSR_PATM3 _DD_MAKEMASK1(30)
+#define M_WCSR_MPR _DD_MAKEMASK1(31)
+
+
+/* 0x44 PCR: Pause Control/Status Register */
+
+#define S_PCR_PAUSE_CNT 0
+#define M_PCR_PAUSE_CNT _DD_MAKEMASK(16,S_PCR_PAUSE_CNT)
+#define V_PCR_PAUSE_CNT(x) _DD_MAKEVALUE(x,S_PCR_PAUSE_CNT)
+#define G_PCR_PAUSE_CNT(x) _DD_GETVALUE(x,S_PCR_PAUSE_CNT,M_PCR_PAUSE_CNT)
+
+#define M_PCR_MLD_EN _DD_MAKEMASK1(16)
+#define M_PCR_PSNEG _DD_MAKEMASK1(21)
+#define M_PCR_PS_RCVD _DD_MAKEMASK1(22)
+#define M_PCR_PS_ACT _DD_MAKEMASK1(23)
+#define M_PCR_PS_DA _DD_MAKEMASK1(29)
+#define M_PCR_PS_MCAST _DD_MAKEMASK1(30)
+#define M_PCR_PSEN _DD_MAKEMASK1(31)
+
+
+/* 0x48 RFCR: Receive Filter/Match Control Register */
+
+
+#define S_RFCR_RFADDR 0
+#define M_RFCR_RFADDR _DD_MAKEMASK(10,S_RFCR_RFADDR)
+#define V_RFCR_RFADDR(x) _DD_MAKEVALUE(x,S_RFCR_RFADDR)
+#define G_RFCR_RFADDR(x) _DD_GETVALUE(x,S_RFCR_RFADDR,M_RFCR_RFADDR)
+
+#define K_RFCR_PMATCH_ADDR 0x000
+#define K_RFCR_PCOUNT_ADDR 0x006
+#define K_RFCR_FILTER_ADDR 0x200
+
+#define M_RFCR_ULM _DD_MAKEMASK1(19)
+#define M_RFCR_UHEN _DD_MAKEMASK1(20)
+#define M_RFCR_MHEN _DD_MAKEMASK1(21)
+#define M_RFCR_AARP _DD_MAKEMASK1(22)
+#define M_RFCR_APAT0 _DD_MAKEMASK1(23)
+#define M_RFCR_APAT1 _DD_MAKEMASK1(24)
+#define M_RFCR_APAT2 _DD_MAKEMASK1(25)
+#define M_RFCR_APAT3 _DD_MAKEMASK1(26)
+#define M_RFCR_APAT (M_RFCR_APAT0 | M_RFCR_APAT1 | \
+ M_RFCR_APAT2 | M_RFCR_APAT3 )
+#define M_RFCR_APM _DD_MAKEMASK1(27)
+#define M_RFCR_AAU _DD_MAKEMASK1(28)
+#define M_RFCR_AAM _DD_MAKEMASK1(29)
+#define M_RFCR_AAB _DD_MAKEMASK1(30)
+#define M_RFCR_RFEN _DD_MAKEMASK1(31)
+
+
+/* 0x4C RFDR: Receive Filter/Match Data Register */
+
+#define S_RFDR_RFDATA 0
+#define M_RFDR_RFDATA _DD_MAKEMASK(16,S_RFDR_RFDATA)
+#define V_RFDR_RFDATA(x) _DD_MAKEVALUE(x,S_RFDR_RFDATA)
+#define G_RFDR_RFDATA(x) _DD_GETVALUE(x,S_RFDR_RFDATA,M_RFDR_RFDATA)
+
+#define S_RFDR_BMASK 16
+#define M_RFDR_BMASK _DD_MAKEMASK(2,S_RFDR_BMASK)
+#define V_RFDR_BMASK(x) _DD_MAKEVALUE(x,S_RFDR_BMASK)
+#define G_RFDR_BMASK(x) _DD_GETVALUE(x,S_RFDR_BMASK,M_RFDR_BMASK)
+
+
+/* 0x50 BRAR: Boot ROM Address Register */
+
+#define S_BRAR_ADDR 0
+#define M_BRAR_ADDR _DD_MAKEMASK(16,S_BRAR_ADDR)
+#define V_BRAR_ADDR(x) _DD_MAKEVALUE(x,S_BRAR_ADDR)
+#define G_BRAR_ADDR(x) _DD_GETVALUE(x,S_BRAR_ADDR,M_BRAR_ADDR)
+
+#define M_BRAR_AUTOINC _DD_MAKEMASK1(31)
+
+
+/* 0x54 BRDR: Boot ROM Data Register */
+
+
+/* 0x58 SRR: Silicon Revision Register */
+
+#define S_SRR_REV 0
+#define M_SRR_REV _DD_MAKEMASK(16,S_SRR_REV)
+#define V_SRR_REV(x) _DD_MAKEVALUE(x,S_SRR_REV)
+#define G_SRR_REV(x) _DD_GETVALUE(x,S_SRR_REV,M_SRR_REV)
+
+#define K_REV_CVNG 0x00000302
+#define K_REV_DVNG_UJB 0x00000403
+
+
+/* 0x5C MIBC: Management Information Base Control Register */
+
+#define M_MIBC_WRN _DD_MAKEMASK1(0)
+#define M_MIBC_FRZ _DD_MAKEMASK1(1)
+#define M_MIBC_ACLR _DD_MAKEMASK1(2)
+#define M_MIBC_MIBS _DD_MAKEMASK1(3)
+
+
+/* MIB Counters */
+
+/* 0x60 RXErroredPkts */
+/* 0x64 RXFCSErrors */
+/* 0x68 RXMsdPktErrors */
+/* 0x6C RXFAErrors */
+/* 0x70 RXSymbolErrors */
+/* 0x74 RXFrameTooLong */
+/* 0x78 TXSQEErrors */
+
+
+/* See ../net/mii.h for fields of standard (MII) PHY registers */
+
+#define K_83815_PHYID1 0x2000
+#define K_83815_PHYID2 0x5C21
+
+#define K_ANNPTR_NULL 0x0001
+
+
+/* 0xC0 PHYSTS: PHY Status Register */
+
+#define PHYSTS_RXERRLATCH 0x2000
+#define PHYSTS_POLARITYSTAT 0x1000
+#define PHYSTS_FALSECARRLATCH 0x0800
+#define PHYSTS_SIGNALDETECT 0x0400
+#define PHYSTS_DESCRAMBLOCK 0x0200
+#define PHYSTS_PAGERECVD 0x0100
+#define PHYSTS_MIIINT 0x0080
+#define PHYSTS_REMOTEFAULT 0x0040
+#define PHYSTS_JABBERDET 0x0020
+#define PHYSTS_ANCOMPLETE 0x0010
+#define PHYSTS_LOOPBACK 0x0008
+#define PHYSTS_DUPLEX 0x0004
+#define PHYSTS_SPEED10 0x0002
+#define PHYSTS_LINKSTAT 0x0001
+
+
+/* 0xC4 MICR: MII Interrupt Control Register */
+
+#define MICR_INTEN 0x0002
+#define MICR_TINT 0x0001
+
+
+/* 0xC8 MISR: MII Interrupt Status and Misc. Control Register */
+
+#define MISR_MINT 0x8000
+#define MISR_MSKLINK 0x4000
+#define MISR_MSKJAB 0x2000
+#define MISR_MSKRF 0x1000
+#define MISR_MSKANC 0x0800
+#define MISR_MSKFHF 0x0400
+#define MISR_MSKRHF 0x0200
+
+
+/* 0xD0 FCSCR: False Carrier Sense Counter Register */
+
+#define FCSCR_FCSCNT 0x00FF
+
+
+/* 0xD4 RECR: Receiver Error Counter Register */
+
+#define RECR_RXERCNT 0x00FF
+
+
+/* 0xD8 PCSR: 100 Mb/s PCS Configuration and Status Register */
+
+#define PCSR_BYP4B5B 0x1000
+#define PCSR_FREECLK 0x0800
+#define PCSR_TQEN 0x0400
+#define PCSR_SDFORCEB 0x0200
+#define PCSR_SDOPTION 0x0100
+#define PCSR_FORCE100OK 0x0020
+#define PCSR_NRZIBYPASS 0x0004
+
+
+/* 0xE4 PHYCR: PHY Control Register */
+
+#define PHYCR_PSR15 0x0800
+#define PHYCR_BISTSTATUS 0x0400
+#define PHYCR_BISTSTART 0x0200
+#define PHYCR_BPSTRETCH 0x0100
+#define PHYCR_PAUSESTS 0x0080
+#define PHYCR_PHYADDR 0x001F
+
+
+/* 0xE8 TBTSCR: 10Base-T Status/Control Register */
+
+#define TBTSCR_LPBK10DIS 0x0100
+#define TBTSCR_LPDIS 0x0080
+#define TBTSCR_FORCELINK10 0x0040
+#define TBTSCR_FORCEPOLCOR 0x0020
+#define TBTSCR_POLARITY 0x0010
+#define TBTSCR_AUTOPOLDIS 0x0008
+#define TBTSCR_HBDIS 0x0002
+#define TBTSCR_JABBERDIS 0x0001
+
+
+/* MacPhyter Transmit and Receive Descriptors */
+
+/* Common Command/Status Fields */
+#define S_DES1_SIZE 0
+#define M_DES1_SIZE _DD_MAKEMASK(12,S_DES1_SIZE)
+#define V_DES1_SIZE(x) _DD_MAKEVALUE(x,S_DES1_SIZE)
+#define G_DES1_SIZE(x) _DD_GETVALUE(x,S_DES1_SIZE,M_DES1_SIZE)
+
+#define M_DES1_OK _DD_MAKEMASK1(27)
+#define M_DES1_INTR _DD_MAKEMASK1(29)
+#define M_DES1_MORE _DD_MAKEMASK1(30)
+#define M_DES1_OWN _DD_MAKEMASK1(31)
+
+/* Transmit Command/Status Bits */
+#define S_DES1_CCNT 16
+#define M_DES1_CCNT _DD_MAKEMASK(4,S_DES1_CCNT)
+#define V_DES1_CCNT(x) _DD_MAKEVALUE(x,S_DES1_CCNT)
+#define G_DES1_CCNT(x) _DD_GETVALUE(x,S_DES1_CCNT,M_DES1_CCNT)
+
+#define M_DES1_EC _DD_MAKEMASK1(20)
+#define M_DES1_OWC _DD_MAKEMASK1(21)
+#define M_DES1_ED _DD_MAKEMASK1(22)
+#define M_DES1_TD _DD_MAKEMASK1(23)
+#define M_DES1_CRS _DD_MAKEMASK1(24)
+#define M_DES1_TFU _DD_MAKEMASK1(25)
+#define M_DES1_TXA _DD_MAKEMASK1(26)
+#define M_DES1_SUPCRC _DD_MAKEMASK1(28)
+
+/* Receive Command/Status Bits */
+#define M_DES1_COL _DD_MAKEMASK1(16)
+#define M_DES1_LBP _DD_MAKEMASK1(17)
+#define M_DES1_FAE _DD_MAKEMASK1(18)
+#define M_DES1_CRCE _DD_MAKEMASK1(19)
+#define M_DES1_ISE _DD_MAKEMASK1(20)
+#define M_DES1_RUNT _DD_MAKEMASK1(21)
+#define M_DES1_LONG _DD_MAKEMASK1(22)
+#define M_DES1_RX_ERRORS (M_DES1_CRCE | \
+ M_DES1_COL | M_DES1_FAE | M_DES1_ISE | \
+ M_DES1_RUNT | M_DES1_LONG | M_DES1_RXO)
+
+#define S_DES1_DEST 23
+#define M_DES1_DEST _DD_MAKEMASK(2,S_DES1_DEST)
+#define V_DES1_DEST(x) _DD_MAKEVALUE(x,S_DES1_DEST)
+#define G_DES1_DEST(x) _DD_GETVALUE(x,S_DES1_DEST,M_DES1_DEST)
+
+#define K_DEST_REJECT 0
+#define K_DEST_UNICAST 1
+#define K_DEST_MULTICAST 2
+#define K_DEST_BROADCAST 3
+
+#define M_DES1_RXO _DD_MAKEMASK1(25)
+#define M_DES1_RXA _DD_MAKEMASK1(26)
+#define M_DES1_INCCRC _DD_MAKEMASK1(28)
+
+#endif /* _DP83815_H_ */
diff --git a/cfe/cfe/dev/ns16550.h b/cfe/cfe/dev/ns16550.h
new file mode 100644
index 0000000..b603ccc
--- /dev/null
+++ b/cfe/cfe/dev/ns16550.h
@@ -0,0 +1,143 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * NS16550 Serial Port definitions File: ns16550.h
+ *
+ * This defines the hardware registers of 16550 compatible UARTs
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+/*
+ * NS16550 UART registers
+ */
+
+#ifndef _NS16550_H_
+#define _NS16550_H_
+
+#ifndef NS16550_HZ
+#define NS16550_HZ 1843200
+#endif
+
+/*
+ * NS16550 UART registers
+ */
+
+/* Register definitions */
+
+#define R_UART_DATA 0
+#define R_UART_IER 1
+#define R_UART_IIR 2
+#define R_UART_FIFO R_UART_IIR
+#define R_UART_CFCR 3
+#define R_UART_MCR 4
+#define R_UART_LSR 5
+#define R_UART_MSR 6
+#define R_UART_SCR 7
+
+/* 16 bit baud rate divisor (lower byte in UART_DATA, upper in UART_IER) */
+#define BRTC(x) (NS16550_HZ / (16*(x)))
+
+/* interrupt enable register */
+#define IER_ERXRDY 0x1 /* int on rx ready */
+#define IER_ETXRDY 0x2 /* int on tx ready */
+#define IER_ERLS 0x4 /* int on line status change */
+#define IER_EMSC 0x8 /* int on modem status change */
+
+/* interrupt identification register */
+#define IIR_IMASK 0xf /* mask */
+#define IIR_RXTOUT 0xc /* receive timeout */
+#define IIR_RLS 0x6 /* receive line status */
+#define IIR_RXRDY 0x4 /* receive ready */
+#define IIR_TXRDY 0x2 /* transmit ready */
+#define IIR_NOPEND 0x1 /* nothing */
+#define IIR_MLSC 0x0 /* modem status */
+#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */
+
+/* fifo control register */
+#define FIFO_ENABLE 0x01 /* enable fifo */
+#define FIFO_RCV_RST 0x02 /* reset receive fifo */
+#define FIFO_XMT_RST 0x04 /* reset transmit fifo */
+#define FIFO_DMA_MODE 0x08 /* enable dma mode */
+#define FIFO_TRIGGER_1 0x00 /* trigger at 1 char */
+#define FIFO_TRIGGER_4 0x40 /* trigger at 4 chars */
+#define FIFO_TRIGGER_8 0x80 /* trigger at 8 chars */
+#define FIFO_TRIGGER_14 0xc0 /* trigger at 14 chars */
+
+/* character format control register */
+#define CFCR_DLAB 0x80 /* divisor latch */
+#define CFCR_SBREAK 0x40 /* send break */
+#define CFCR_PZERO 0x30 /* zero parity */
+#define CFCR_PONE 0x20 /* one parity */
+#define CFCR_PEVEN 0x10 /* even parity */
+#define CFCR_PODD 0x00 /* odd parity */
+#define CFCR_PENAB 0x08 /* parity enable */
+#define CFCR_STOPB 0x04 /* 2 stop bits */
+#define CFCR_8BITS 0x03 /* 8 data bits */
+#define CFCR_7BITS 0x02 /* 7 data bits */
+#define CFCR_6BITS 0x01 /* 6 data bits */
+#define CFCR_5BITS 0x00 /* 5 data bits */
+
+/* modem control register */
+#define MCR_LOOPBACK 0x10 /* loopback */
+#define MCR_IENABLE 0x08 /* output 2 = int enable */
+#define MCR_DRS 0x04 /* output 1 = xxx */
+#define MCR_RTS 0x02 /* enable RTS */
+#define MCR_DTR 0x01 /* enable DTR */
+
+/* line status register */
+#define LSR_RCV_FIFO 0x80 /* error in receive fifo */
+#define LSR_TSRE 0x40 /* transmitter empty */
+#define LSR_TXRDY 0x20 /* transmitter ready */
+#define LSR_BI 0x10 /* break detected */
+#define LSR_FE 0x08 /* framing error */
+#define LSR_PE 0x04 /* parity error */
+#define LSR_OE 0x02 /* overrun error */
+#define LSR_RXRDY 0x01 /* receiver ready */
+#define LSR_RCV_MASK 0x1f
+
+/* modem status register */
+#define MSR_DCD 0x80 /* DCD active */
+#define MSR_RI 0x40 /* RI active */
+#define MSR_DSR 0x20 /* DSR active */
+#define MSR_CTS 0x10 /* CTS active */
+#define MSR_DDCD 0x08 /* DCD changed */
+#define MSR_TERI 0x04 /* RI changed */
+#define MSR_DDSR 0x02 /* DSR changed */
+#define MSR_DCTS 0x01 /* CTS changed */
+
+#endif /* _NS16550_H_ */
diff --git a/cfe/cfe/dev/pci_devs.c b/cfe/cfe/dev/pci_devs.c
new file mode 100644
index 0000000..a1ba789
--- /dev/null
+++ b/cfe/cfe/dev/pci_devs.c
@@ -0,0 +1,79 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * PCI device selection and initialization File: pci_devs.c
+ *
+ * These are the routines to include the PCI drivers and to hook any
+ * devices with special configuration requirements..
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#if CFG_PCI
+#include "sbmips.h"
+#include "lib_types.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "dev_ide.h"
+#include "env_subr.h"
+
+extern cfe_driver_t pciidedrv; /* PCI IDE controller */
+extern cfe_driver_t dc21143drv; /* Tulip Ethernet */
+extern cfe_driver_t dp83815drv; /* MacPhyter Ethernet */
+#if CFG_DOWNLOAD
+extern cfe_driver_t bcm1250drv; /* BCM1250 as a device */
+#endif
+extern cfe_driver_t ns16550pci_uart; /* PCI serial port */
+
+void pci_add_devices(int init_pci);
+void pci_add_devices(int init_pci)
+{
+ if (init_pci) {
+ cfe_add_device(&pciidedrv,0,IDE_PROBE_MASTER_TYPE(IDE_DEVTYPE_DISK),NULL);
+ cfe_add_device(&dc21143drv,0,0,env_getenv("TULIP0_HWADDR"));
+ cfe_add_device(&dp83815drv,0,0,NULL);
+
+#if CFG_DOWNLOAD
+ /* Access to bcm1250 in PCI device mode */
+ cfe_add_device(&bcm1250drv,0,0,NULL);
+#endif
+ cfe_add_device(&ns16550pci_uart,0,0,0);
+ }
+}
+#endif /* CFG_PCI */
+
diff --git a/cfe/cfe/hosttools/Makefile b/cfe/cfe/hosttools/Makefile
new file mode 100644
index 0000000..2f04639
--- /dev/null
+++ b/cfe/cfe/hosttools/Makefile
@@ -0,0 +1,12 @@
+
+CC = gcc
+CFLAGS = -I ../include
+
+all : mkbootimage installboot
+
+mkbootimage : mkbootimage.c
+ $(CC) $(CFLAGS) -o mkbootimage mkbootimage.c
+
+installboot : installboot.c
+ $(CC) $(CFLAGS) -o installboot installboot.c
+
diff --git a/cfe/cfe/hosttools/README b/cfe/cfe/hosttools/README
new file mode 100644
index 0000000..7976c6d
--- /dev/null
+++ b/cfe/cfe/hosttools/README
@@ -0,0 +1,49 @@
+
+This directory contains some "host tools" that may be useful for
+porting CFE.
+
+MKBOOTIMAGE
+-----------
+
+The 'mkbootimage' program is used to attach a CFE boot block to
+an image file. Boot blocks are used on block-structured devices
+such as disks and CD-ROM.
+
+The boot block contains information to help CFE locate the boot
+loader program and verify its validity. To create boot file,
+link your boot loader to be executable within CFE's boot
+environment (it should be a binary file, not an ELF file).
+
+Convert the file to a boot block using:
+
+ mkbootimage [-EB] [-EL] myfile.elf myfile.boot
+
+Supply the -EB or -EL switch to configure the target endianness,
+since the values in the boot block are endian-specific.
+
+
+INSTALLBOOT
+-----------
+
+Once you have a boot file, the 'installboot' program can
+insert the boot file into a simulated disk file (such as the
+file that you can use with the IDE emulation in the
+BCM12500's functional simulator). The 'installboot' program
+installs your boot file into a disk image file starting at
+the first sector, preserving the beginning part of the boot
+sector where the the boot block lives.
+
+Install the boot block using:
+
+ installboot myfile.boot my_disk_image.dsk
+
+Where the "my_disk_image.dsk" is the simulated disk file for
+the functional simulator.
+
+installboot could probably be ported to the target OS to
+install boot blocks on raw disk devices.
+
+
+
+
+
diff --git a/cfe/cfe/hosttools/installboot.c b/cfe/cfe/hosttools/installboot.c
new file mode 100644
index 0000000..2f61415
--- /dev/null
+++ b/cfe/cfe/hosttools/installboot.c
@@ -0,0 +1,352 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Boot program installer File: installboot.c
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ * This program converts a binary file (bootstrap program)
+ * into a boot block by prepending the boot block sector
+ * to the program. It generates the appropriate
+ * boot block checksums and such. The resulting file may
+ * be used by installboot (for example) to put into a disk
+ * image for the simulator.
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+typedef unsigned long long uint64_t;
+typedef unsigned long uint32_t;
+
+#include "cfe_bootblock.h"
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define roundup(x,align) (((x)+(align)-1)&~((align)-1))
+#define howmany(x,align) (((x)+(align)-1)/(align))
+
+static int verbose = 0;
+static int big_endian = 1;
+static int swapflg = 1;
+static unsigned long bootcode_offset = 2;
+static unsigned long bootsect_offset = 1;
+
+static void usage(void)
+{
+ fprintf(stderr,"usage: installboot [-bootsect <sector offset>] [-bootcode <sector offset>]\n"
+ " [-v] [-EB] [-EL] bootloaderfile.bin devicefile\n\n");
+ fprintf(stderr,"This program installs a boot block onto a disk. Typically, installboot\n"
+ "is used to install sibyl or other OS bootloaders. The binary you install\n"
+ "should be a raw program (not ELF) located to run in CFE's boot area\n"
+ "at address 0x2000_0000. The devicefile should be the name of the raw device\n"
+ "such as /dev/hda on Linux.\n\n"
+ "Care must be taken when choosing the values for -bootsect and -bootcode\n"
+ "not to interfere with other partitions on your disk. When partitioning,\n"
+ "it's a good idea to reserve 3 cylinders at the beginning of the disk for\n"
+ "the boot loader.\n\n"
+ "-bootsect nn specifies that the boot sector will be placed on sector 'nn'\n"
+ "-bootcode nn specifies that the boot program itself will be placed\n"
+ " on sectors starting with 'nn'. The boot sector will point\n"
+ " to this sector.\n");
+
+ exit(1);
+}
+
+static void bswap32(uint32_t *ptr)
+{
+ unsigned char b;
+ unsigned char *bptr;
+
+ if (swapflg) {
+ bptr = (unsigned char *) ptr;
+ b = bptr[0]; bptr[0] = bptr[3]; bptr[3] = b;
+ b = bptr[1]; bptr[1] = bptr[2]; bptr[2] = b;
+ }
+}
+
+static void bswap64(uint64_t *ptr)
+{
+ unsigned char b;
+ unsigned char *bptr;
+
+ bptr = (unsigned char *) ptr;
+
+ if (swapflg) {
+ b = bptr[0]; bptr[0] = bptr[7]; bptr[7] = b;
+ b = bptr[1]; bptr[1] = bptr[6]; bptr[6] = b;
+ b = bptr[2]; bptr[2] = bptr[5]; bptr[5] = b;
+ b = bptr[3]; bptr[3] = bptr[4]; bptr[4] = b;
+ }
+}
+
+
+static void bswap_bootblock(struct boot_block *bb)
+{
+ int idx;
+
+ for (idx = 59; idx <= 63; idx++) {
+ bswap64(&(bb->bb_data[idx]));
+ }
+}
+
+static void do_checksum(void *ptr,int length,uint32_t *csptr,int swap)
+{
+ uint32_t *p;
+ uint32_t chksum = 0;
+ uint32_t d;
+
+ p = (uint32_t *) ptr;
+
+ length /= sizeof(uint32_t);
+
+ while (length) {
+ d = *p;
+ if (swap) bswap32(&d);
+ chksum += d;
+ p++;
+ length--;
+ }
+
+ if (swap) bswap32(&chksum);
+
+ *csptr = chksum;
+}
+
+
+static void dumpbootblock(struct boot_block *bb)
+{
+ int idx;
+
+ fprintf(stderr,"Magic Number: %016llX\n",
+ bb->bb_magic);
+ fprintf(stderr,"Boot code offset: %llu\n",
+ (unsigned long long)bb->bb_secstart);
+ fprintf(stderr,"Boot code size: %u\n",
+ (uint32_t) (bb->bb_secsize & BOOT_SECSIZE_MASK));
+ fprintf(stderr,"Header checksum: %08X\n",
+ (uint32_t) (bb->bb_hdrinfo & BOOT_HDR_CHECKSUM_MASK));
+ fprintf(stderr,"Header version: %d\n",
+ (uint32_t) ((bb->bb_hdrinfo & BOOT_HDR_VER_MASK) >> BOOT_HDR_VER_SHIFT));
+ fprintf(stderr,"Data checksum: %08X\n",
+ (uint32_t) ((bb->bb_secsize & BOOT_DATA_CHECKSUM_MASK) >> BOOT_DATA_CHECKSUM_SHIFT));
+ fprintf(stderr,"Architecture info: %08X\n",
+ (uint32_t) (bb->bb_archinfo & BOOT_ARCHINFO_MASK));
+ fprintf(stderr,"\n");
+
+ for (idx = 59; idx <= 63; idx++) {
+ fprintf(stderr,"Word %d = %016llX\n",idx,bb->bb_data[idx]);
+ }
+}
+
+static int host_is_little(void)
+{
+ unsigned long var = 1;
+ unsigned char *pvar = (unsigned char *) &var;
+
+ return (*pvar == 1);
+}
+
+int main(int argc, char *argv[])
+{
+ int fh;
+ long bootsize;
+ long bootbufsize;
+ unsigned char *bootcode;
+ struct boot_block bootblock;
+ uint32_t datacsum,hdrcsum;
+ int host_le;
+
+ while ((argc > 1) && (argv[1][0] == '-')) {
+ if (strcmp(argv[1],"-v") == 0) {
+ verbose = 1;
+ }
+ else if (strcmp(argv[1],"-EB") == 0) {
+ big_endian = 1;
+ }
+ else if (strcmp(argv[1],"-EL") == 0) {
+ big_endian = 0;
+ }
+ else if (strcmp(argv[1],"-bootsect") == 0) {
+ char *tmp_ptr;
+ argv++;
+ argc--;
+ if (argc == 1) {
+ fprintf(stderr,"-bootsect requires an argument\n");
+ exit(1);
+ }
+ bootsect_offset = strtoul(argv[1], &tmp_ptr, 0);
+ bootcode_offset = bootsect_offset + 1; /* default if -bootcode not specified */
+ if (*tmp_ptr) {
+ fprintf(stderr,"Unable to parse %s as a sector offset\n", argv[1]);
+ exit(1);
+ }
+ }
+ else if (strcmp(argv[1],"-bootcode") == 0) {
+ char *tmp_ptr;
+ argv++;
+ argc--;
+ if (argc == 1) {
+ fprintf(stderr,"-bootcode requires an argument\n");
+ exit(1);
+ }
+ bootcode_offset = strtoul(argv[1], &tmp_ptr, 0);
+ if (*tmp_ptr) {
+ fprintf(stderr,"Unable to parse %s as a sector offset\n", argv[1]);
+ exit(1);
+ }
+ }
+ else {
+ fprintf(stderr,"Invalid switch: %s\n",argv[1]);
+ exit(1);
+ }
+ argv++;
+ argc--;
+ }
+
+ /*
+ * We need to swap things around if the host and
+ * target are different endianness
+ */
+
+ swapflg = 0;
+ host_le = host_is_little();
+
+ if (big_endian && host_is_little()) swapflg = 1;
+ if ((big_endian == 0) && !(host_is_little())) swapflg = 1;
+
+ fprintf(stderr,"Host is %s-endian.\n",host_le ? "little" : "big");
+ fprintf(stderr,"Target is %s-endian.\n",big_endian ? "big" : "little");
+
+ if (argc != 3) {
+ usage();
+ }
+
+ /*
+ * Read in the boot file
+ */
+
+ fh = open(argv[1],O_RDONLY);
+ if (fh < 0) {
+ perror(argv[1]);
+ }
+
+ bootsize = lseek(fh,0L,SEEK_END);
+ lseek(fh,0L,SEEK_SET);
+
+ bootbufsize = roundup(bootsize,BOOT_BLOCK_BLOCKSIZE);
+
+ bootcode = malloc(bootbufsize);
+ if (bootcode == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ memset(bootcode,0,bootbufsize);
+ if (read(fh,bootcode,bootsize) != bootsize) {
+ perror("read");
+ exit(1);
+ }
+
+ close(fh);
+
+ /*
+ * Construct the boot block
+ */
+
+
+ /* Checksum the boot code */
+ do_checksum(bootcode,bootbufsize,&datacsum,1);
+ bswap32(&datacsum);
+
+
+ /* fill in the boot block fields, and checksum the boot block */
+ bootblock.bb_magic = BOOT_MAGIC_NUMBER;
+ bootblock.bb_hdrinfo = (((uint64_t) BOOT_HDR_VERSION) << BOOT_HDR_VER_SHIFT);
+ bootblock.bb_secstart = (bootcode_offset * 512);
+ bootblock.bb_secsize = ((uint64_t) bootbufsize) |
+ (((uint64_t) datacsum) << BOOT_DATA_CHECKSUM_SHIFT);
+ bootblock.bb_archinfo = 0; /* XXX */
+
+ do_checksum(&(bootblock.bb_magic),BOOT_BLOCK_SIZE,&hdrcsum,0);
+ bootblock.bb_hdrinfo |= (uint64_t) hdrcsum;
+
+ if (verbose) dumpbootblock(&bootblock);
+
+ bswap_bootblock(&bootblock);
+
+ /*
+ * Now write the output file
+ */
+
+ fh = open(argv[2],O_RDWR|O_CREAT,S_IREAD|S_IWRITE);
+ if (fh < 0) {
+ perror(argv[2]);
+ exit(1);
+ }
+
+ fprintf(stderr,"Installing boot block\n");
+ if (lseek(fh, bootsect_offset * 512, SEEK_SET) != (bootsect_offset * 512)) {
+ perror(argv[2]);
+ exit(1);
+ }
+ if (write(fh,&bootblock,sizeof(bootblock)) != sizeof(bootblock)) {
+ perror(argv[2]);
+ exit(1);
+ }
+ fprintf(stderr,"Installing bootstrap program\n");
+ if (lseek(fh, bootcode_offset * 512, SEEK_SET) != (bootcode_offset * 512)) {
+ perror(argv[2]);
+ exit(1);
+ }
+ if (write(fh,bootcode,bootbufsize) != bootbufsize) {
+ perror(argv[2]);
+ exit(1);
+ }
+
+ close(fh);
+
+ fprintf(stderr,"Done. %s installed on %s\n",argv[1],argv[2]);
+
+ exit(0);
+
+
+}
+
diff --git a/cfe/cfe/hosttools/makereg.c b/cfe/cfe/hosttools/makereg.c
new file mode 100644
index 0000000..0ff53e1
--- /dev/null
+++ b/cfe/cfe/hosttools/makereg.c
@@ -0,0 +1,481 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Register Table Generator File: makereg.c
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ * Warning: don't eat your lunch before reading this program.
+ * It's nasty!
+ *
+ * This program generates tables of SOC registers and values
+ * that are easy for us to display.
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+
+#if defined(_MSC_VER) || defined(__CYGWIN__)
+#define TEXTMODE "t"
+#else
+#define TEXTMODE ""
+#endif
+
+typedef struct Cons {
+ char *str;
+ int num;
+} CONS;
+
+typedef struct RegInfo {
+ unsigned long reg_mask;
+ char *reg_agent;
+ int reg_agentidx;
+ char *reg_addr;
+ char *reg_inst;
+ char *reg_subinst;
+ char *reg_printfunc;
+ char *reg_description;
+} REGINFO;
+
+typedef struct ConstInfo {
+ char *name;
+ unsigned int value;
+} CONSTINFO;
+
+#define MAXCONST 64
+CONSTINFO constants[MAXCONST];
+int constcnt = 0;
+
+#define MAXREGS 2000
+REGINFO allregs[MAXREGS];
+int regcnt = 0;
+
+int maskcnt = 0;
+
+#define MAXAGENTS 32
+char *agentnames[MAXAGENTS];
+int agentcnt;
+
+#define CMD_AGENT 1
+#define CMD_ENDAGENT 2
+
+CONS commands[] = {
+ {"!agent",CMD_AGENT},
+ {"!endagent",CMD_ENDAGENT},
+ {NULL,0}};
+
+
+int assoc(CONS *list,char *str)
+{
+ while (list->str) {
+ if (strcmp(list->str,str) == 0) return list->num;
+ list++;
+ }
+
+ return -1;
+}
+
+char *gettoken(char **ptr)
+{
+ char *p = *ptr;
+ char *ret;
+
+ /* skip white space */
+
+ while (*p && isspace(*p)) p++;
+ ret = p;
+
+ /* check for end of string */
+
+ if (!*p) {
+ *ptr = p;
+ return NULL;
+ }
+
+ /* skip non-whitespace */
+
+ while (*p) {
+ if (isspace(*p)) break;
+
+ /* do quoted strings */
+
+ if (*p == '"') {
+ p++;
+ ret = p;
+ while (*p && (*p != '"')) p++;
+ if (*p == '"') *p = '\0';
+ }
+
+ p++;
+
+ }
+
+ if (*p) {
+ *p++ = '\0';
+ }
+ *ptr = p;
+
+ return ret;
+}
+
+static int readline(FILE *str,char *dest,int destlen)
+{
+ char *x;
+
+ for (;;) {
+ if (!fgets(dest,destlen,str)) return -1;
+ if (x = strchr(dest,'\n')) *x = '\0';
+ if (dest[0] == '\0') continue;
+ if (dest[0] == ';') continue;
+ break;
+ }
+
+ return 0;
+}
+
+
+static void fatal(char *str,char *val)
+{
+ fprintf(stderr,"fatal error: %s %s\n",str,val ? val : "");
+ exit(1);
+}
+
+static unsigned int newmask(void)
+{
+ int res;
+
+ res = maskcnt;
+
+ if (maskcnt == 32) {
+ fatal("Out of mask bits",NULL);
+ }
+
+ maskcnt++;
+
+ return 1<<res;
+}
+
+static void addconst(char *name,unsigned int val)
+{
+ if (constcnt == MAXCONST) {
+ fatal("Out of constant space",NULL);
+ }
+
+ constants[constcnt].name = strdup(name);
+ constants[constcnt].value = val;
+
+ constcnt++;
+}
+
+static void addreg(
+ char *agentname,
+ int agentidx,
+ unsigned long mask,
+ char *addr,
+ char *inst,
+ char *subinst,
+ char *printfunc,
+ char *description)
+{
+ allregs[regcnt].reg_mask = mask;
+ allregs[regcnt].reg_addr = strdup(addr);
+ allregs[regcnt].reg_agent = strdup(agentname);
+ allregs[regcnt].reg_agentidx = agentidx;
+ allregs[regcnt].reg_inst = strdup(inst);
+ allregs[regcnt].reg_subinst = strdup(subinst);
+ allregs[regcnt].reg_printfunc = strdup(printfunc);
+ allregs[regcnt].reg_description = strdup(description);
+ regcnt++;
+}
+
+
+static void macroexpand(char *instr,char *exp,char *outstr)
+{
+ while (*instr) {
+ if (*instr == '$') {
+ strcpy(outstr,exp);
+ outstr += strlen(outstr);
+ instr++;
+ }
+ else {
+ *outstr++ = *instr++;
+ }
+ }
+
+ *outstr = '\0';
+}
+
+
+static void doagentcmd(FILE *str,char *line)
+{
+ char *agentname;
+ char *instances;
+ char *inst;
+ char *ptr;
+ char regline[500];
+ char cumlname[100];
+ REGINFO regs[100];
+ char temp[20];
+ int rmax = 0;
+ int idx;
+ unsigned int cumlmask;
+ int agentidx;
+
+ agentname = gettoken(&line);
+ instances = gettoken(&line);
+ if (!instances) {
+ strcpy(temp,"*");
+ instances = temp;
+ }
+
+ fprintf(stderr,"Agent %s Instances %s\n",agentname,instances);
+
+ if (agentcnt == MAXAGENTS) {
+ fatal("Out of agent slots\n",NULL);
+ }
+
+ agentnames[agentcnt] = strdup(agentname);
+ agentidx = agentcnt;
+ agentcnt++;
+
+ regline[0] = '\0';
+
+ while ((readline(str,regline,sizeof(regline)) >= 0) && (rmax < 100)) {
+ char *atext,*subinst,*pfunc,*descr;
+
+ if (regline[0] == '!') break;
+
+ ptr = regline;
+ atext = gettoken(&ptr);
+ subinst = gettoken(&ptr);
+ pfunc = gettoken(&ptr);
+ descr = gettoken(&ptr);
+
+ if (!descr) {
+ fatal("Missing fields for ",atext);
+ }
+
+ regs[rmax].reg_addr = strdup(atext);
+ regs[rmax].reg_subinst = strdup(subinst);
+ regs[rmax].reg_printfunc = strdup(pfunc);
+ regs[rmax].reg_description = strdup(descr);
+ regs[rmax].reg_mask = 0;
+ rmax++;
+ }
+
+ if (rmax == 100) fatal("Too many registers in section ",agentname);
+
+ inst = strtok(instances,",");
+
+ cumlmask = 0;
+ while (inst) {
+ char defname[100];
+ unsigned int curmask;
+
+ sprintf(defname,"SOC_AGENT_%s%s",
+ agentname,inst[0] == '*' ? "" : inst);
+
+ curmask = newmask();
+ cumlmask |= curmask;
+
+ addconst(defname,curmask);
+
+ for (idx = 0; idx < rmax; idx++) {
+ char descr[100];
+ char atext[200];
+
+ macroexpand(regs[idx].reg_addr,inst,atext);
+#if 0
+ strcpy(descr,agentname);
+ if (inst[0] != '*') {
+ strcat(descr,inst);
+ }
+ strcat(descr," ");
+ if (regs[idx].reg_subinst[0] != '*') {
+ strcat(descr,regs[idx].reg_subinst);
+ strcat(descr," ");
+ }
+ strcat(descr,regs[idx].reg_description);
+#else
+ strcpy(descr,regs[idx].reg_description);
+#endif
+
+ addreg(agentname,
+ agentidx,
+ curmask,
+ atext,
+ inst,
+ regs[idx].reg_subinst,
+ regs[idx].reg_printfunc,
+ descr);
+ }
+ inst = strtok(NULL,",");
+ }
+
+ if (instances[0] != '*') {
+ sprintf(cumlname,"SOC_AGENT_%s",agentname);
+ addconst(cumlname,cumlmask);
+ }
+}
+
+static void docommand(FILE *str,char *line)
+{
+ char *cmd;
+
+ cmd = gettoken(&line);
+ if (!cmd) return;
+
+ switch (assoc(commands,cmd)) {
+ case CMD_AGENT:
+ doagentcmd(str,line);
+ break;
+ default:
+ fatal("Invalid command",cmd);
+ break;
+ }
+
+}
+
+static int ingestfile(FILE *str)
+{
+ char line[500];
+
+ while (readline(str,line,sizeof(line)) >= 0) {
+ if (line[0] == '!') {
+ docommand(str,line);
+ }
+ else {
+ fatal("Command string required before register data",NULL);
+ }
+ }
+}
+
+
+void saveincfile(char *fname)
+{
+ FILE *str;
+ int idx;
+
+ str = fopen(fname,"w" TEXTMODE);
+ if (!str) {
+ perror(fname);
+ exit(1);
+ }
+
+ fprintf(str,"\n\n");
+
+ fprintf(str,"#ifndef %s\n",constants[0].name);
+ for (idx = 0; idx < constcnt; idx++) {
+ fprintf(str,"#define %s 0x%08X\n",constants[idx].name,
+ constants[idx].value);
+ }
+ fprintf(str,"#endif\n");
+
+ fprintf(str,"\n\n");
+
+ fprintf(str,"#ifdef _CFE_\n");
+ fprintf(str,"#ifdef __ASSEMBLER__\n");
+ fprintf(str,"\t.globl socstatetable\n");
+ fprintf(str,"socstatetable:\n");
+ for (idx = 0; idx < regcnt; idx++) {
+ fprintf(str,"\t\t.word 0x%08X,%s\n",
+ allregs[idx].reg_mask,allregs[idx].reg_addr);
+ }
+ fprintf(str,"\t\t.word 0,0\n");
+ fprintf(str,"#endif\n");
+
+ fprintf(str,"\n\n");
+ fprintf(str,"#ifndef __ASSEMBLER__\n");
+
+ /* Addr Agent Inst Subinst Mask Printfunc Descr */
+
+ fprintf(str,"char *socagents[] = {\n");
+ for (idx = 0; idx < agentcnt; idx++) {
+ fprintf(str,"\t\"%s\",\n",agentnames[idx]);
+ }
+ fprintf(str,"\tNULL};\n\n");
+
+ fprintf(str,"const socreg_t socregs[] = {\n");
+ for (idx = 0; idx < regcnt; idx++) {
+ fprintf(str," {%s,%d,\"%s\",\"%s\",\n 0x%08X,%s,\"%s\"},\n",
+ allregs[idx].reg_addr,
+ allregs[idx].reg_agentidx,
+ allregs[idx].reg_inst,
+ allregs[idx].reg_subinst,
+ allregs[idx].reg_mask,
+ allregs[idx].reg_printfunc,
+ allregs[idx].reg_description);
+ }
+ fprintf(str," {0,0,NULL,NULL,0,NULL,NULL}};\n\n");
+
+ fprintf(str,"#endif\n");
+ fprintf(str,"#endif\n");
+ fclose(str);
+}
+
+int main(int argc,char *argv[])
+{
+ FILE *str;
+ int idx;
+
+ if (argc != 3) {
+ fprintf(stderr,"usage: makereg inputfile outputfile\n");
+ exit(1);
+ }
+
+ str = fopen(argv[1],"r" TEXTMODE);
+
+ if (!str) {
+ perror(argv[1]);
+ exit(1);
+ }
+
+ ingestfile(str);
+
+ fclose(str);
+
+ fprintf(stderr,"Total registers: %d\n",regcnt);
+
+ saveincfile(argv[2]);
+
+ exit(0);
+ return 0;
+}
diff --git a/cfe/cfe/hosttools/memconfig.c b/cfe/cfe/hosttools/memconfig.c
new file mode 100644
index 0000000..3d84b05
--- /dev/null
+++ b/cfe/cfe/hosttools/memconfig.c
@@ -0,0 +1,654 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Memory Config Utility File: memconfig.c
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ * This host tool lets you enter DRAM parameters and run CFE's
+ * standard memory configuration to calculate the relevant timing
+ * parameters. It's a good way to see what CFE would have done,
+ * to find bogus timing calculations.
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include <stdio.h>
+#include <string.h>
+
+/* *********************************************************************
+ * Basic types
+ ********************************************************************* */
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned long uint32_t;
+typedef unsigned long long uint64_t;
+
+/* *********************************************************************
+ * SB1250 stuff
+ ********************************************************************* */
+
+#include "sb1250_defs.h"
+#include "sb1250_mc.h"
+#include "sb1250_draminit.h"
+#include "sb1250_regs.h"
+#include "sb1250_scd.h"
+
+/* *********************************************************************
+ * BCD macros
+ ********************************************************************* */
+
+#define DECTO10THS(x) ((((x) >> 4)*10)+((x) & 0x0F))
+
+/* *********************************************************************
+ * Global defaults
+ ********************************************************************* */
+
+#define MIN_tMEMCLK DRT10(8,0)
+#define tROUNDTRIP DRT10(2,5)
+
+/* *********************************************************************
+ * Types
+ ********************************************************************* */
+
+typedef struct encvalue_s {
+ char *name;
+ uint8_t val;
+} encvalue_t;
+
+typedef struct spdbyte_s {
+ char *name;
+ uint8_t *data;
+ int decimal;
+ encvalue_t *values;
+ char *units;
+ char *description;
+ char *deflt;
+} spdbyte_t;
+
+#define SPD_DEC_BCD 1
+#define SPD_DEC_QTR 2
+#define SPD_ENCODED 3
+#define SPD_ENCODED2 4
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+
+uint8_t spd[64] = {0}; /* SPD data */
+uint8_t mintmemclk = MIN_tMEMCLK; /* Default value: 8.0ns */
+uint8_t roundtrip = tROUNDTRIP; /* Default value: 2.5ns */
+uint8_t dramtype = JEDEC; /* Regular DDR SDRAMs */
+uint8_t plldiv = 10; /* 500 MHz using 100Mhz refclk */
+uint8_t refclk = 100; /* 100Mhz reference clock */
+uint8_t portintlv = 0; /* no port interleaving */
+
+uint8_t addrskew = 0xF;
+uint8_t dqoskew = 0x8;
+uint8_t dqiskew = 0x8;
+uint8_t addrdrive = 0xF;
+uint8_t datadrive = 0xF;
+uint8_t clkdrive = 0;
+
+uint64_t mc0_mclkcfg; /* Value programmed by draminit */
+uint64_t mc0_timing1; /* Value programmed by draminit */
+uint64_t smbus0_start = 0; /* Rememberd SMBus register value */
+uint64_t smbus0_cmd = 0; /* Rememberd SMBus register value */
+
+extern int sb1250_refclk; /* from draminit - reference clock */
+extern int dram_cas_latency; /* from draminit - calc'd cas latency */
+extern int dram_tMemClk; /* from draminit - calc'd tMemClk */
+
+draminittab_t inittab[16]; /* our init tab */
+
+int debug = 0;
+
+/* *********************************************************************
+ * Parameter and value tables
+ ********************************************************************* */
+
+encvalue_t caslatencies[] = {
+ {"3.5",JEDEC_CASLAT_35},
+ {"3.0",JEDEC_CASLAT_30},
+ {"2.5",JEDEC_CASLAT_25},
+ {"2.0",JEDEC_CASLAT_20},
+ {"1.5",JEDEC_CASLAT_15},
+ {"1.0",JEDEC_CASLAT_10},
+ {NULL,0}};
+
+encvalue_t refreshrates[] = {
+ {"64",JEDEC_RFSH_64khz},
+ {"256",JEDEC_RFSH_256khz},
+ {"128",JEDEC_RFSH_128khz},
+ {"32",JEDEC_RFSH_32khz},
+ {"16",JEDEC_RFSH_16khz},
+ {"8",JEDEC_RFSH_8khz},
+ {NULL,0}};
+
+encvalue_t modattribs[] = {
+ {"none",0},
+ {"reg",JEDEC_ATTRIB_REG},
+ {"diffclk",0x20},
+ {NULL,0}};
+
+encvalue_t dramtypes[] = {
+ {"jedec",JEDEC},
+ {"fcram",FCRAM},
+ {"sgram",SGRAM},
+ {NULL,0}};
+
+spdbyte_t spdfields[] = {
+ {"mintmemclk",&mintmemclk,SPD_DEC_BCD,NULL,"ns","Minimum value for tMEMCLK","8.0"},
+ {"roundtrip", &roundtrip, SPD_DEC_BCD,NULL,"ns","Round trip time from CLK to returned DQS","2.5"},
+ {"plldiv", &plldiv, 0,NULL,"","PLL Ratio (System Config Register)","10"},
+ {"refclk", &refclk, 0,NULL,"Mhz","Reference clock, usually 100Mhz","100"},
+// {"portintlv", &portintlv, 0,NULL,"","Port interleave (1=on)","0"},
+ {"memtype", &dramtype, SPD_ENCODED,dramtypes,"","Memory type (jedec, fcram, sgram)","jedec"},
+ {"rows", &spd[JEDEC_SPD_ROWS],0,NULL,"","[3 ] Number of row bits","13"},
+ {"cols", &spd[JEDEC_SPD_COLS],0,NULL,"","[4 ] Number of column bits","9"},
+ {"banks", &spd[JEDEC_SPD_BANKS],0,NULL,"","[17] Number of banks","4"},
+ {"tCK25", &spd[JEDEC_SPD_tCK25],SPD_DEC_BCD,NULL,"ns","[9 ] tCK value for CAS Latency 2.5","7.5"},
+ {"tCK20", &spd[JEDEC_SPD_tCK20],SPD_DEC_BCD,NULL,"ns","[23] tCK value for CAS Latency 2.0","0"},
+ {"tCK10", &spd[JEDEC_SPD_tCK10],SPD_DEC_BCD,NULL,"ns","[25] tCK value for CAS Latency 1.0","0"},
+ {"rfsh", &spd[JEDEC_SPD_RFSH],SPD_ENCODED,refreshrates,"","[12] Refresh rate (KHz)","8"},
+ {"caslat", &spd[JEDEC_SPD_CASLATENCIES],SPD_ENCODED2,caslatencies,"","[18] CAS Latencies supported","2.5"},
+ {"attrib", &spd[JEDEC_SPD_ATTRIBUTES],SPD_ENCODED,modattribs,"","[21] Module attributes","none"},
+ {"tRAS", &spd[JEDEC_SPD_tRAS],0,NULL,"ns","[30]","45"},
+ {"tRP", &spd[JEDEC_SPD_tRP],SPD_DEC_QTR,NULL,"ns","[27]","20.0"},
+ {"tRRD", &spd[JEDEC_SPD_tRRD],SPD_DEC_QTR,NULL,"ns","[28]","15.0"},
+ {"tRCD", &spd[JEDEC_SPD_tRCD],SPD_DEC_QTR,NULL,"ns","[29]","20.0"},
+ {"tRFC", &spd[JEDEC_SPD_tRFC],0,NULL,"ns","[42]","0"},
+ {"tRC", &spd[JEDEC_SPD_tRC],0,NULL,"ns","[41]","0"},
+
+ {"addrskew", &addrskew, 0, NULL, "","Address Skew","0x0F"},
+ {"dqoskew", &dqoskew, 0, NULL, "","DQO Skew","0x08"},
+ {"dqikew", &dqiskew, 0, NULL, "","DQI Skew","0x08"},
+ {"addrdrive", &addrdrive, 0, NULL, "","Address Drive","0x0F"},
+ {"datadrive", &datadrive, 0, NULL, "","Data Drive","0x0F"},
+ {"clkdrive", &clkdrive, 0, NULL, "","Clock Drive","0"},
+ {NULL,0,0,NULL,NULL,NULL,NULL}};
+
+char *lookupstr(encvalue_t *ev,uint8_t val)
+{
+ while (ev->name) {
+ if (ev->val == val) return ev->name;
+ ev++;
+ }
+ return "unknown";
+}
+
+uint64_t sbreadcsr(uint64_t reg)
+{
+ uint64_t val = 0;
+
+ if (debug) printf("READ %08X\n",(uint32_t) reg);
+
+ switch ((uint32_t) reg) {
+ case A_SCD_SYSTEM_REVISION:
+ val = V_SYS_PART(0x1250) | V_SYS_WID(0) | V_SYS_REVISION(1) | 0xFF;
+ break;
+ case A_SCD_SYSTEM_CFG:
+ val = V_SYS_PLL_DIV(plldiv);
+ break;
+ case A_SMB_STATUS_0:
+ val = 0;
+ break;
+ case A_SMB_CMD_0:
+ val = smbus0_cmd;
+ break;
+ case A_SMB_START_0:
+ val = smbus0_start;
+ break;
+ case A_SMB_DATA_0:
+ val = spd[smbus0_cmd & 0x3F];
+ break;
+ }
+ return val;
+}
+
+void sbwritecsr(uint64_t reg,uint64_t val)
+{
+ if (debug) printf("WRITE %08X %016llX\n",(uint32_t) reg,val);
+
+ switch ((uint32_t) reg) {
+ case A_MC_REGISTER(0,R_MC_MCLK_CFG):
+ mc0_mclkcfg = val;
+ break;
+ case A_MC_REGISTER(0,R_MC_TIMING1):
+ mc0_timing1 = val;
+ break;
+ case A_SMB_CMD_0:
+ smbus0_cmd = val;
+ break;
+ case A_SMB_START_0:
+ smbus0_start = val;
+ break;
+ }
+}
+
+
+int procfield(char *txt)
+{
+ int num = 0;
+ int a,b;
+ spdbyte_t *sf;
+ encvalue_t *ev;
+ char *x;
+ char *tok;
+
+ x = strchr(txt,'=');
+ if (!x) {
+ printf("Fields must be specified as 'name=value'\n");
+ exit(1);
+ }
+ *x++ = '\0';
+
+ sf = spdfields;
+ while (sf->name) {
+ if (strcmp(sf->name,txt) == 0) break;
+ sf++;
+ }
+
+ if (sf->name == NULL) {
+ printf("Invalid field name: %s\n",txt);
+ return -1;
+ }
+
+ if (memcmp(x,"0x",2) == 0) {
+ sscanf(x+2,"%x",&num);
+ }
+ else {
+ if (strchr(x,'.')) {
+ if (sscanf(x,"%d.%d",&a,&b) != 2) {
+ printf("%s: invalid number: %s\n",sf->name,x);
+ return -1;
+ }
+ }
+ else {
+ a = atoi(x);
+ b = 0;
+ }
+
+ switch (sf->decimal) {
+ case SPD_DEC_BCD:
+ if ((b < 0) || (b > 9)) {
+ printf("%s: Invalid BCD number: %s\n",sf->name,x);
+ return -1;
+ }
+ num = (a*16)+b;
+ break;
+ case SPD_DEC_QTR:
+ if ((b != 0) && (b != 25) && (b != 50) && (b != 75)) {
+ printf("%s: Invalid 2-bit fraction number: %s\n",sf->name,x);
+ printf("(number after decimal should be 0,25,50,75)\n");
+ exit(1);
+ }
+ num = (a*4)+(b/25);
+ break;
+ case SPD_ENCODED:
+ ev = sf->values;
+ while (ev->name) {
+ if (strcmp(ev->name,x) == 0) break;
+ ev++;
+ }
+ if (!ev->name) {
+ printf("%s: Invalid value. Valid values are: ",x);
+ ev = sf->values;
+ while (ev->name) { printf("%s ",ev->name); ev++; }
+ printf("\n");
+ return -1;
+ }
+ num = ev->val;
+ break;
+ case SPD_ENCODED2:
+ tok = strtok(x," ,");
+ num = 0;
+ while (tok) {
+ ev = sf->values;
+ while (ev->name) {
+ if (strcmp(ev->name,tok) == 0) break;
+ ev++;
+ }
+ if (!ev->name) {
+ printf("%s: Invalid value. Valid values are: ",tok);
+ ev = sf->values;
+ while (ev->name) { printf("%s ",ev->name); ev++; }
+ printf("\n");
+ return -1;
+ }
+ num |= ev->val;
+ tok = strtok(NULL," ,");
+ }
+ break;
+ default:
+ num = a;
+ break;
+ }
+ }
+
+ *(sf->data) = num;
+
+ return 0;
+}
+
+void interactive(void)
+{
+ spdbyte_t *sf;
+ char field[100];
+ char ask[100];
+ char prompt[100];
+ char *x;
+
+ sf = spdfields;
+
+ printf("%-65.65s: Value\n","Parameter");
+ printf("%-65.65s: -----\n","-----------------------------------------------------------------");
+
+ while (sf->name) {
+ for (;;) {
+ x = prompt;
+ x += sprintf(x,"%s (%s", sf->name,sf->description);
+ if (sf->units && sf->units[0]) {
+ if (sf->description && sf->description[0]) x += sprintf(x,", ");
+ x += sprintf(x,"%s",sf->units);
+ }
+ x += sprintf(x,"): [%s]", sf->deflt);
+ printf("%-65.65s: ",prompt);
+
+ fgets(ask,sizeof(ask),stdin);
+ if ((x = strchr(ask,'\n'))) *x = '\0';
+ if (ask[0] == 0) strcpy(ask,sf->deflt);
+ sprintf(field,"%s=%s",sf->name,ask);
+ if (procfield(field) < 0) continue;
+ break;
+ }
+ sf++;
+ }
+
+ printf("\n\n");
+}
+
+int swcnt = 0;
+char *swnames[32];
+
+int proc_args(int argc,char *argv[])
+{
+ int inidx,outidx;
+
+ outidx = 1;
+
+ for (inidx = 1; inidx < argc; inidx++) {
+ if (argv[inidx][0] != '-') {
+ argv[outidx++] = argv[inidx];
+ }
+ else {
+ swnames[swcnt] = argv[inidx];
+ swcnt++;
+ }
+ }
+
+ return outidx;
+}
+
+int swisset(char *x)
+{
+ int idx;
+
+ for (idx = 0; idx < swcnt; idx++) {
+ if (strcmp(x,swnames[idx]) == 0) return 1;
+ }
+ return 0;
+}
+
+void dumpmclkcfg(uint64_t val)
+{
+ printf("clk_ratio = %d\n",G_MC_CLK_RATIO(val));
+ printf("ref_rate = %d\n",G_MC_REF_RATE(val));
+
+}
+
+void dumptiming1(uint64_t val)
+{
+ printf("w2rIdle = %d\n",(val & M_MC_w2rIDLE_TWOCYCLES) ? 1 : 0);
+ printf("r2rIdle = %d\n",(val & M_MC_r2rIDLE_TWOCYCLES) ? 1 : 0);
+ printf("r2wIdle = %d\n",(val & M_MC_r2wIDLE_TWOCYCLES) ? 1 : 0);
+ printf("tCrD = %d\n",(int)G_MC_tCrD(val));
+ printf("tCrDh = %d\n",(val & M_MC_tCrDh) ? 1 : 0);
+ printf("tFIFO = %d\n",(int)G_MC_tFIFO(val));
+ printf("tCwD = %d\n",(int)G_MC_tCwD(val));
+
+ printf("tRP = %d\n",(int)G_MC_tRP(val));
+ printf("tRRD = %d\n",(int)G_MC_tRRD(val));
+ printf("tRCD = %d\n",(int)G_MC_tRCD(val));
+
+ printf("tRFC = %d\n",(int)G_MC_tRFC(val));
+ printf("tRCw = %d\n",(int)G_MC_tRCw(val));
+ printf("tRCr = %d\n",(int)G_MC_tRCr(val));
+ printf("tCwCr = %d\n",(int)G_MC_tCwCr(val));
+}
+
+int main(int argc,char *argv[])
+{
+ spdbyte_t *sf;
+ uint8_t t;
+ int idx;
+ int mclk;
+ draminittab_t *init;
+
+ spd[JEDEC_SPD_MEMTYPE] = JEDEC_MEMTYPE_DDRSDRAM2;
+ spd[JEDEC_SPD_ROWS] = 13;
+ spd[JEDEC_SPD_COLS] = 9;
+ spd[JEDEC_SPD_BANKS] = 2;
+ spd[JEDEC_SPD_SIDES] = 1;
+ spd[JEDEC_SPD_WIDTH] = 72;
+
+ argc = proc_args(argc,argv);
+
+ if ((argc == 1) && !swisset("-i")) {
+ printf("usage: memconfig name=value name=value ...\n");
+ printf("\n");
+ printf("Available fields: ");
+ sf = spdfields;
+ while (sf->name) {
+ printf("%s ",sf->name);
+ sf++;
+ }
+ printf("\n");
+ exit(1);
+ }
+
+ if (swisset("-i")) {
+ interactive();
+ }
+ else {
+ for (idx = 1; idx < argc; idx++) {
+ if (procfield(argv[idx]) < 0) exit(1);
+ }
+ }
+
+ debug = swisset("-d");
+
+ printf("-------Memory Parameters---------\n");
+
+ sf = spdfields;
+ while (sf->name) {
+ char buffer[64];
+ char *p = buffer;
+
+ t = *(sf->data);
+ printf("%-10.10s = 0x%02X ",sf->name,t);
+ switch (sf->decimal) {
+ case SPD_DEC_BCD:
+ p += sprintf(p,"(%d.%d)",
+ t >> 4, t & 0x0F);
+ break;
+ case SPD_DEC_QTR:
+ p += sprintf(p,"(%d.%02d)",
+ t/4,(t&3)*25);
+ break;
+ case SPD_ENCODED:
+ p += sprintf(p,"(%s)",lookupstr(sf->values,t));
+ break;
+ default:
+ p += sprintf(p,"(%d)",t);
+ break;
+ }
+
+ p += sprintf(p," %s",sf->units);
+ printf("%-16.16s %s\n",buffer,sf->description);
+ sf++;
+ }
+
+ printf("\n");
+
+ init = &inittab[0];
+ memset(inittab,0,sizeof(inittab));
+
+ init->gbl.gbl_type = MCR_GLOBALS;
+ init->gbl.gbl_intlv_ch = portintlv;
+ init++;
+
+ init->cfg.cfg_type = MCR_CHCFG;
+ init->cfg.cfg_chan = 0;
+ init->cfg.cfg_mintmemclk = mintmemclk;
+ init->cfg.cfg_dramtype = dramtype;
+ init->cfg.cfg_pagepolicy = CASCHECK;
+ init->cfg.cfg_blksize = BLKSIZE32;
+ init->cfg.cfg_intlv_cs = NOCSINTLV;
+ init->cfg.cfg_ecc = 0;
+ init->cfg.cfg_roundtrip = roundtrip;
+ init++;
+
+ init->clk.clk_type = MCR_CLKCFG;
+ init->clk.clk_addrskew = addrskew;
+ init->clk.clk_dqoskew = dqoskew;
+ init->clk.clk_dqiskew = dqiskew;
+ init->clk.clk_addrdrive = addrdrive;
+ init->clk.clk_datadrive = datadrive;
+ init->clk.clk_clkdrive = clkdrive;
+ init++;
+
+ init->geom.geom_type = MCR_GEOM;
+ init->geom.geom_csel = 0;
+ init->geom.geom_rows = spd[JEDEC_SPD_ROWS];
+ init->geom.geom_cols = spd[JEDEC_SPD_COLS];
+ init->geom.geom_banks = spd[JEDEC_SPD_BANKS];
+ init++;
+
+#if 0
+ init->tmg.tmg_type = MCR_TIMING;
+ init->tmg.tmg_tCK = spd[JEDEC_SPD_tCK25];
+ init->tmg.tmg_rfsh = spd[JEDEC_SPD_RFSH];
+ init->tmg.tmg_caslatency = spd[JEDEC_SPD_CASLATENCIES];
+ init->tmg.tmg_attributes = spd[JEDEC_SPD_ATTRIBUTES];
+ init->tmg.tmg_tRAS = spd[JEDEC_SPD_tRAS];
+ init->tmg.tmg_tRP = spd[JEDEC_SPD_tRP];
+ init->tmg.tmg_tRRD = spd[JEDEC_SPD_tRRD];
+ init->tmg.tmg_tRCD = spd[JEDEC_SPD_tRCD];
+ init->tmg.tmg_tRFC = spd[JEDEC_SPD_tRFC];
+ init->tmg.tmg_tRC = spd[JEDEC_SPD_tRC];
+ init++;
+#else
+ init->spd.spd_type = MCR_SPD;
+ init->spd.spd_csel = 0;
+ init->spd.spd_flags = 0;
+ init->spd.spd_smbuschan = 0;
+ init->spd.spd_smbusdev = 0x50;
+ init++;
+#endif
+
+ init->mcr.mcr_type = MCR_EOT;
+
+
+ sb1250_refclk = (int) refclk;
+
+ sb1250_dram_init(inittab);
+
+
+ printf("-----Memory Timing Register Values-----\n");
+ printf("System Clock %dMHz\n",plldiv*refclk/2);
+ printf("CAS latency %d.%d\n",dram_cas_latency>>1,(dram_cas_latency&1)?5:0);
+ printf("tMemClk %d.%d ns\n",dram_tMemClk/10,dram_tMemClk%10);
+ mclk = (plldiv*refclk)*10/2/((int)G_MC_CLK_RATIO(mc0_mclkcfg));
+ printf("MCLK Freq %d.%dMHz\n",mclk/10,mclk%10);
+ printf("\n");
+ printf("MC_TIMING1 = %016llX\n",mc0_timing1);
+ printf("MCLK_CONFIG = %016llX\n",mc0_mclkcfg);
+ printf("\n");
+
+ printf("-----Memory Timing Register Fields-----\n");
+ dumptiming1(mc0_timing1);
+
+ printf("-----Memory Clock Config Register Fields-----\n");
+ dumpmclkcfg(mc0_mclkcfg);
+
+ printf("---Done!---\n");
+
+ printf("%s ",argv[0]);
+ sf = spdfields;
+ while (sf->name) {
+ char buffer[64];
+ char *p = buffer;
+
+ t = *(sf->data);
+
+ p += sprintf(p,"%s=",sf->name);
+ switch (sf->decimal) {
+ case SPD_DEC_BCD:
+ p += sprintf(p,"%d.%d",
+ t >> 4, t & 0x0F);
+ break;
+ case SPD_DEC_QTR:
+ p += sprintf(p,"%d.%02d",
+ t/4,(t&3)*25);
+ break;
+ case SPD_ENCODED:
+ default:
+ p += sprintf(p,"0x%02X",t);
+ break;
+ }
+
+ printf("%s ",buffer);
+ sf++;
+ }
+
+ printf("\n");
+
+ return 0;
+}
diff --git a/cfe/cfe/hosttools/mkbootimage.c b/cfe/cfe/hosttools/mkbootimage.c
new file mode 100644
index 0000000..862f8ed
--- /dev/null
+++ b/cfe/cfe/hosttools/mkbootimage.c
@@ -0,0 +1,314 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Boot block generator File: mkbootimage.c
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ * This program converts a binary file (bootstrap program)
+ * into a boot block by prepending the boot block sector
+ * to the program. It generates the appropriate
+ * boot block checksums and such. The resulting file may
+ * be used by installboot (for example) to put into a disk
+ * image for the simulator.
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+typedef unsigned long long uint64_t;
+typedef unsigned long uint32_t;
+
+#include "cfe_bootblock.h"
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define roundup(x,align) (((x)+(align)-1)&~((align)-1))
+#define howmany(x,align) (((x)+(align)-1)/(align))
+
+static int verbose = 0;
+static int big_endian = 1;
+static int swapflg = 1;
+static unsigned long sector_offset = 0;
+
+static void usage(void)
+{
+ fprintf(stderr,"usage: mkbootimage [-S <sector offset>] [-v] [-EB] [-EL] inputfile outputfile\n");
+ exit(1);
+}
+
+static void bswap32(uint32_t *ptr)
+{
+ unsigned char b;
+ unsigned char *bptr;
+
+ if (swapflg) {
+ bptr = (unsigned char *) ptr;
+ b = bptr[0]; bptr[0] = bptr[3]; bptr[3] = b;
+ b = bptr[1]; bptr[1] = bptr[2]; bptr[2] = b;
+ }
+}
+
+static void bswap64(uint64_t *ptr)
+{
+ unsigned char b;
+ unsigned char *bptr;
+
+ bptr = (unsigned char *) ptr;
+
+ if (swapflg) {
+ b = bptr[0]; bptr[0] = bptr[7]; bptr[7] = b;
+ b = bptr[1]; bptr[1] = bptr[6]; bptr[6] = b;
+ b = bptr[2]; bptr[2] = bptr[5]; bptr[5] = b;
+ b = bptr[3]; bptr[3] = bptr[4]; bptr[4] = b;
+ }
+}
+
+
+static void bswap_bootblock(struct boot_block *bb)
+{
+ int idx;
+
+ for (idx = 59; idx <= 63; idx++) {
+ bswap64(&(bb->bb_data[idx]));
+ }
+}
+
+static void do_checksum(void *ptr,int length,uint32_t *csptr,int swap)
+{
+ uint32_t *p;
+ uint32_t chksum = 0;
+ uint32_t d;
+
+ p = (uint32_t *) ptr;
+
+ length /= sizeof(uint32_t);
+
+ while (length) {
+ d = *p;
+ if (swap) bswap32(&d);
+ chksum += d;
+ p++;
+ length--;
+ }
+
+ if (swap) bswap32(&chksum);
+
+ *csptr = chksum;
+}
+
+
+static void dumpbootblock(struct boot_block *bb)
+{
+ int idx;
+
+ fprintf(stderr,"Magic Number: %016llX\n",
+ bb->bb_magic);
+ fprintf(stderr,"Boot code offset: %llu\n",
+ (unsigned long long)bb->bb_secstart);
+ fprintf(stderr,"Boot code size: %u\n",
+ (uint32_t) (bb->bb_secsize & BOOT_SECSIZE_MASK));
+ fprintf(stderr,"Header checksum: %08X\n",
+ (uint32_t) (bb->bb_hdrinfo & BOOT_HDR_CHECKSUM_MASK));
+ fprintf(stderr,"Header version: %d\n",
+ (uint32_t) ((bb->bb_hdrinfo & BOOT_HDR_VER_MASK) >> BOOT_HDR_VER_SHIFT));
+ fprintf(stderr,"Data checksum: %08X\n",
+ (uint32_t) ((bb->bb_secsize & BOOT_DATA_CHECKSUM_MASK) >> BOOT_DATA_CHECKSUM_SHIFT));
+ fprintf(stderr,"Architecture info: %08X\n",
+ (uint32_t) (bb->bb_archinfo & BOOT_ARCHINFO_MASK));
+ fprintf(stderr,"\n");
+
+ for (idx = 59; idx <= 63; idx++) {
+ fprintf(stderr,"Word %d = %016llX\n",idx,bb->bb_data[idx]);
+ }
+}
+
+static int host_is_little(void)
+{
+ unsigned long var = 1;
+ unsigned char *pvar = (unsigned char *) &var;
+
+ return (*pvar == 1);
+}
+
+int main(int argc, char *argv[])
+{
+ int fh;
+ long bootsize;
+ long bootbufsize;
+ unsigned char *bootcode;
+ struct boot_block bootblock;
+ uint32_t datacsum,hdrcsum;
+ int host_le;
+
+ while ((argc > 1) && (argv[1][0] == '-')) {
+ if (strcmp(argv[1],"-v") == 0) {
+ verbose = 1;
+ }
+ else if (strcmp(argv[1],"-EB") == 0) {
+ big_endian = 1;
+ }
+ else if (strcmp(argv[1],"-EL") == 0) {
+ big_endian = 0;
+ }
+ else if (strcmp(argv[1],"-S") == 0) {
+ char *tmp_ptr;
+ argv++;
+ argc--;
+ if (argc == 1) {
+ fprintf(stderr,"-S requires an argument\n");
+ exit(1);
+ }
+ sector_offset = strtoul(argv[1], &tmp_ptr, 0);
+ if (*tmp_ptr) {
+ fprintf(stderr,"Unable to parse %s as a sector offset\n", argv[1]);
+ exit(1);
+ }
+ }
+ else {
+ fprintf(stderr,"Invalid switch: %s\n",argv[1]);
+ exit(1);
+ }
+ argv++;
+ argc--;
+ }
+
+ /*
+ * We need to swap things around if the host and
+ * target are different endianness
+ */
+
+ swapflg = 0;
+ host_le = host_is_little();
+
+ if (big_endian && host_is_little()) swapflg = 1;
+ if ((big_endian == 0) && !(host_is_little())) swapflg = 1;
+
+ fprintf(stderr,"Host is %s-endian.\n",host_le ? "little" : "big");
+ fprintf(stderr,"Target is %s-endian.\n",big_endian ? "big" : "little");
+
+ if (argc != 3) {
+ usage();
+ }
+
+ /*
+ * Read in the boot file
+ */
+
+ fh = open(argv[1],O_RDONLY);
+ if (fh < 0) {
+ perror(argv[1]);
+ }
+
+ bootsize = lseek(fh,0L,SEEK_END);
+ lseek(fh,0L,SEEK_SET);
+
+ bootbufsize = roundup(bootsize,BOOT_BLOCK_BLOCKSIZE);
+
+ bootcode = malloc(bootbufsize);
+ if (bootcode == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ memset(bootcode,0,bootbufsize);
+ if (read(fh,bootcode,bootsize) != bootsize) {
+ perror("read");
+ exit(1);
+ }
+
+ close(fh);
+
+ /*
+ * Construct the boot block
+ */
+
+
+ /* Checksum the boot code */
+ do_checksum(bootcode,bootbufsize,&datacsum,1);
+ bswap32(&datacsum);
+
+
+ /* fill in the boot block fields, and checksum the boot block */
+ bootblock.bb_magic = BOOT_MAGIC_NUMBER;
+ bootblock.bb_hdrinfo = (((uint64_t) BOOT_HDR_VERSION) << BOOT_HDR_VER_SHIFT);
+ bootblock.bb_secstart = BOOT_BLOCK_BLOCKSIZE + (sector_offset * 512);
+ bootblock.bb_secsize = ((uint64_t) bootbufsize) |
+ (((uint64_t) datacsum) << BOOT_DATA_CHECKSUM_SHIFT);
+ bootblock.bb_archinfo = 0; /* XXX */
+
+ do_checksum(&(bootblock.bb_magic),BOOT_BLOCK_SIZE,&hdrcsum,0);
+ bootblock.bb_hdrinfo |= (uint64_t) hdrcsum;
+
+ if (verbose) dumpbootblock(&bootblock);
+
+ bswap_bootblock(&bootblock);
+
+ /*
+ * Now write the output file
+ */
+
+ fh = open(argv[2],O_RDWR|O_CREAT,S_IREAD|S_IWRITE);
+ if (fh < 0) {
+ perror(argv[2]);
+ exit(1);
+ }
+ if (lseek(fh, sector_offset * 512, SEEK_SET) != (sector_offset * 512)) {
+ perror(argv[2]);
+ exit(1);
+ }
+ if (write(fh,&bootblock,sizeof(bootblock)) != sizeof(bootblock)) {
+ perror(argv[2]);
+ exit(1);
+ }
+ if (write(fh,bootcode,bootbufsize) != bootbufsize) {
+ perror(argv[2]);
+ exit(1);
+ }
+
+ close(fh);
+
+ fprintf(stderr,"%s -> %s : OK\n",argv[1],argv[2]);
+
+ exit(0);
+
+
+}
+
diff --git a/cfe/cfe/hosttools/mkflashimage.c b/cfe/cfe/hosttools/mkflashimage.c
new file mode 100644
index 0000000..84ec77c
--- /dev/null
+++ b/cfe/cfe/hosttools/mkflashimage.c
@@ -0,0 +1,347 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Flash Image generator File: mkflashimage.c
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ * This program sticks a header on the front of a binary
+ * file making it suitable for use with the 'flash' command
+ * in CFE. The header contains the CFE version # and board
+ * type, a CRC, and other info to help prevent us from
+ * flashing bad stuff onto a board.
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifndef _SYS_INT_TYPES_H
+typedef unsigned char uint8_t;
+typedef unsigned long long uint64_t;
+typedef unsigned long uint32_t;
+#endif
+
+#include "cfe_flashimage.h"
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+
+static int verbose = 0;
+static int big_endian = 1;
+static int both_endian = 0;
+int mlong64 = 0;
+char boardname[32];
+
+/*
+ * This is the offset in the flash where the little-endian image goes
+ * if we're making a bi-endian flash.
+ */
+
+#define CFE_BIENDIAN_LE_OFFSET (1024*1024)
+
+static void usage(void)
+{
+ fprintf(stderr,"usage: mkflashimage [-v] [-EB] [-EL] [-64] [-B boardname] [-V v.v.v] binfile outfile\n");
+ fprintf(stderr,"\n");
+ fprintf(stderr," mkflashimage [-v] -EX [-64] [-B boardname] [-V v.v.v] BE-binfile LE-binfile outfile\n");
+ fprintf(stderr," (this variant used for making bi-endian flash files)\n");
+ exit(1);
+}
+
+
+static int host_is_little(void)
+{
+ unsigned long var = 1;
+ unsigned char *pvar = (unsigned char *) &var;
+
+ return (*pvar == 1);
+}
+
+#define CRC32_POLY 0xEDB88320UL /* CRC-32 Poly */
+
+static unsigned int
+crc32(const unsigned char *databuf, unsigned int datalen)
+{
+ unsigned int idx, bit, data, crc = 0xFFFFFFFFUL;
+
+ for (idx = 0; idx < datalen; idx++) {
+ for (data = *databuf++, bit = 0; bit < 8; bit++, data >>= 1) {
+ crc = (crc >> 1) ^ (((crc ^ data) & 1) ? CRC32_POLY : 0);
+ }
+ }
+
+ return crc;
+}
+
+
+void stuff_be32(uint8_t *dest,unsigned int src)
+{
+ *dest++ = (src >> 24) & 0xFF;
+ *dest++ = (src >> 16) & 0xFF;
+ *dest++ = (src >> 8) & 0xFF;
+ *dest++ = (src >> 0) & 0xFF;
+}
+
+int main(int argc, char *argv[])
+{
+ int fh;
+ int flashsize;
+ unsigned char *flashcode;
+ cfe_flashimage_t header;
+ int host_le;
+ int majver,minver,ecover;
+ uint32_t crc;
+ uint32_t flags;
+ char *outfile;
+
+ majver = minver = ecover = 0;
+ boardname[0] = 0;
+
+ while ((argc > 1) && (argv[1][0] == '-')) {
+ if (strcmp(argv[1],"-v") == 0) {
+ verbose = 1;
+ }
+ else if (strcmp(argv[1],"-EX") == 0) {
+ if (verbose) fprintf(stderr,"[Image file will be marked Bi-Endian]\n");
+ both_endian = 1;
+ }
+ else if (strcmp(argv[1],"-EB") == 0) {
+ if (verbose) fprintf(stderr,"[Image file will be marked Big-Endian]\n");
+ big_endian = 1;
+ }
+ else if (strcmp(argv[1],"-EL") == 0) {
+ if (verbose) fprintf(stderr,"[Image file will be marked Little-Endian]\n");
+ big_endian = 0;
+ }
+ else if (strcmp(argv[1],"-64") == 0) {
+ if (verbose) fprintf(stderr,"[Image file will be marked 64-bit]\n");
+ mlong64 = 1;
+ }
+ else if (strcmp(argv[1],"-B") == 0) {
+ argc--;
+ argv++;
+ strcpy(boardname,argv[1]);
+ if (verbose) fprintf(stderr,"[Board name: %s]\n",boardname);
+ }
+ else if (strcmp(argv[1],"-V") == 0) {
+ argc--;
+ argv++;
+ sscanf(argv[1],"%d.%d.%d",&majver,&minver,&ecover);
+ if (verbose) fprintf(stderr,"[Image version: %d.%d.%d]\n",majver,minver,ecover);
+ }
+ else {
+ fprintf(stderr,"Invalid switch: %s\n",argv[1]);
+ exit(1);
+ }
+ argv++;
+ argc--;
+ }
+
+ /*
+ * We need to swap things around if the host and
+ * target are different endianness
+ */
+
+ host_le = host_is_little();
+
+ if (verbose) {
+ fprintf(stderr,"Host is %s-endian.\n",host_le ? "little" : "big");
+ if (both_endian) {
+ fprintf(stderr,"Target is bi-endian.\n");
+ }
+ else {
+ fprintf(stderr,"Target is %s-endian.\n",big_endian ? "big" : "little");
+ }
+ }
+
+ if ((both_endian && (argc != 4)) || (!both_endian && (argc != 3))) {
+ usage();
+ }
+
+ /*
+ * Read in the boot file(s)
+ */
+
+ flags = 0;
+
+ if (both_endian) {
+ int be_size;
+
+ flags |= (CFE_IMAGE_EB | CFE_IMAGE_EL);
+
+ if (verbose) fprintf(stderr,"Reading: %s\n",argv[2]);
+
+ fh = open(argv[2],O_RDONLY);
+ if (fh < 0) {
+ perror(argv[2]);
+ }
+
+ flashsize = lseek(fh,0L,SEEK_END);
+ lseek(fh,0L,SEEK_SET);
+
+ flashcode = malloc(flashsize+CFE_BIENDIAN_LE_OFFSET);
+ if (flashcode == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ memset(flashcode,0xFF,flashsize+CFE_BIENDIAN_LE_OFFSET);
+
+ if (read(fh,flashcode+CFE_BIENDIAN_LE_OFFSET,flashsize) != flashsize) {
+ perror("read");
+ exit(1);
+ }
+
+ close(fh);
+
+ if (memcmp(flashcode+CFE_BIENDIAN_LE_OFFSET,CFE_IMAGE_SEAL,4) == 0) {
+ fprintf(stderr,"File '%s' already has an image header.\n",argv[2]);
+ exit(1);
+ }
+
+ flashsize += CFE_BIENDIAN_LE_OFFSET; /* actual file size */
+
+ if (verbose) fprintf(stderr,"Reading: %s\n",argv[1]);
+
+ fh = open(argv[1],O_RDONLY);
+ if (fh < 0) {
+ perror(argv[1]);
+ exit(1);
+ }
+
+ be_size = lseek(fh,0L,SEEK_END);
+ lseek(fh,0L,SEEK_SET);
+ if (be_size > CFE_BIENDIAN_LE_OFFSET) {
+ fprintf(stderr,"File '%s' will not fit within first %d bytes of flash image\n",
+ argv[1],CFE_BIENDIAN_LE_OFFSET);
+ close(fh);
+ exit(1);
+ }
+
+ if (read(fh,flashcode,be_size) != be_size) {
+ perror("read");
+ exit(1);
+ }
+
+ close(fh);
+
+ outfile = argv[3];
+
+ }
+ else {
+ if (big_endian) flags |= CFE_IMAGE_EB;
+ else flags |= CFE_IMAGE_EL;
+
+ fh = open(argv[1],O_RDONLY);
+ if (fh < 0) {
+ perror(argv[1]);
+ exit(1);
+ }
+
+ flashsize = lseek(fh,0L,SEEK_END);
+ lseek(fh,0L,SEEK_SET);
+
+ flashcode = malloc(flashsize);
+ if (flashcode == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ memset(flashcode,0,flashsize);
+ if (read(fh,flashcode,flashsize) != flashsize) {
+ perror("read");
+ exit(1);
+ }
+
+ close(fh);
+
+ if (memcmp(flashcode,CFE_IMAGE_SEAL,4) == 0) {
+ fprintf(stderr,"File '%s' already has an image header.\n",argv[1]);
+ exit(1);
+ }
+
+ outfile = argv[2];
+ }
+
+
+ /*
+ * Construct the flash header
+ */
+
+ if (mlong64) flags |= CFE_IMAGE_MLONG64;
+ crc = crc32(flashcode,flashsize);
+
+ memset(&header,0,sizeof(header));
+ memcpy(header.seal,CFE_IMAGE_SEAL,sizeof(header.seal));
+ stuff_be32(header.flags,flags);
+ stuff_be32(header.size,flashsize);
+ stuff_be32(header.crc,crc);
+ header.majver = majver;
+ header.minver = minver;
+ header.ecover = ecover;
+ header.miscver = 0;
+ strcpy(header.boardname,boardname);
+
+ /*
+ * Now write the output file
+ */
+
+ fh = open(outfile,O_RDWR|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE|S_IRGRP|S_IWGRP|S_IROTH);
+ if (fh < 0) {
+ perror(outfile);
+ exit(1);
+ }
+ if (write(fh,&header,sizeof(header)) != sizeof(header)) {
+ perror(outfile);
+ exit(1);
+ }
+ if (write(fh,flashcode,flashsize) != flashsize) {
+ perror(outfile);
+ exit(1);
+ }
+
+ fprintf(stderr,"Wrote %d bytes to %s\n",sizeof(header)+flashsize,outfile);
+
+ close(fh);
+
+ exit(0);
+
+
+}
+
diff --git a/cfe/cfe/hosttools/mkpcidb.c b/cfe/cfe/hosttools/mkpcidb.c
new file mode 100644
index 0000000..fe7d314
--- /dev/null
+++ b/cfe/cfe/hosttools/mkpcidb.c
@@ -0,0 +1,157 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * PCI Table Generator File: mkpcidb.c
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ * This program munges the PCI table into a form that uses
+ * fewer embedded pointers. Pointers are evil for the
+ * relocatable version of CFE since they chew up valuable
+ * initialized data segment space, and we only have
+ * 64KB of that.
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include <stdio.h>
+
+typedef unsigned short pci_vendor_id_t;
+typedef unsigned short pci_product_id_t;
+
+struct pci_knowndev {
+ pci_vendor_id_t vendor;
+ pci_product_id_t product;
+ int flags;
+ char *vendorname, *productname;
+};
+
+#include "../pci/pcidevs.h"
+#define PCI_KNOWNDEV_NOPROD 0x01
+#include "../pci/pcidevs_data.h"
+
+
+
+struct pci_knowndev2 {
+ pci_vendor_id_t vendor;
+ pci_product_id_t product;
+ int flags;
+ int vendorname;
+ int productname;
+};
+
+#define MAXPCIDEVS 5000
+#define MAXSTRINGTABLE (1024*1024)
+
+struct pci_knowndev2 knowndevs[MAXPCIDEVS];
+char stringtable[MAXSTRINGTABLE];
+int curstringptr = 0;
+
+int allocstring(char *string)
+{
+ int ptr;
+
+ if (!string) return -1;
+
+ ptr = curstringptr;
+ strcpy(&stringtable[ptr],string);
+ curstringptr += strlen(string)+1;
+ return ptr;
+}
+
+int main(int argc,char *argv[])
+{
+ struct pci_knowndev2 *outdev;
+ const struct pci_knowndev *indev;
+ int cnt = 0;
+ int idx;
+
+ indev = pci_knowndevs;
+ outdev = knowndevs;
+ cnt = 0;
+
+ while (indev->vendorname) {
+ outdev->vendor = indev->vendor;
+ outdev->product = indev->product;
+ outdev->flags = indev->flags;
+ outdev->vendorname = allocstring(indev->vendorname);
+ outdev->productname = allocstring(indev->productname);
+ cnt++;
+ indev++;
+ outdev++;
+ }
+
+ outdev->vendor = 0;
+ outdev->product = 0;
+ outdev->flags = 0;
+ outdev->vendorname = -1;
+ outdev->productname = -1;
+ cnt++;
+
+ fprintf(stderr,"%d total devices (%d bytes), %d bytes of strings\n",
+ cnt,cnt*sizeof(struct pci_knowndev2),curstringptr);
+
+ printf("\n\n\n");
+ printf("const static struct pci_knowndev2 _pci_knowndevs[] __attribute__ ((section (\".text\"))) = {\n");
+ for (idx = 0; idx < cnt; idx++) {
+ printf("\t{0x%04X,0x%04X,0x%08X,%d,%d},\n",
+ knowndevs[idx].vendor,
+ knowndevs[idx].product,
+ knowndevs[idx].flags,
+ knowndevs[idx].vendorname,
+ knowndevs[idx].productname);
+ }
+ printf("};\n\n\n");
+ printf("const static char _pci_knowndevs_text[] __attribute__ ((section (\".text\"))) = {\n");
+ for (idx = 0; idx < curstringptr; idx++) {
+ if ((idx % 16) == 0) printf("\t");
+ printf("0x%02X,",stringtable[idx]);
+ if ((idx % 16) == 15) printf("\n");
+ }
+ printf("0};\n\n");
+
+ printf("static const struct pci_knowndev2 *pci_knowndevs = _pci_knowndevs;\n");
+ printf("static const char *pci_knowndevs_text = _pci_knowndevs_text;\n");
+ printf("#define PCI_STRING_NULL (-1)\n");
+ printf("#define PCI_STRING(x) (&pci_knowndevs_text[(x)])\n\n");
+
+
+
+ exit(0);
+}
+
+
diff --git a/cfe/cfe/include/cfe.h b/cfe/cfe/include/cfe.h
new file mode 100755
index 0000000..013fb13
--- /dev/null
+++ b/cfe/cfe/include/cfe.h
@@ -0,0 +1,101 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * CFE version # and prototypes File: cfe.h
+ *
+ * CFE's version # temporarily lives here.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+/* *********************************************************************
+ * Version number
+ ********************************************************************* */
+
+#define CFE_VER_MAJOR CFE_VER_MAJ
+#define CFE_VER_MINOR CFE_VER_MIN
+#define CFE_VER_BUILD CFE_VER_ECO
+
+/* Numbers must not exceed 255 */
+#define BCM63XX_MAJOR 106
+#define BCM63XX_MINOR 24
+
+/* *********************************************************************
+ * Some runtime startup parameters
+ ********************************************************************* */
+#if !defined(__ASSEMBLER__)
+extern unsigned cfe_startflags;
+#endif
+
+#define CFE_INIT_USER 0x0000FFFF /* these are BSP-specific flags */
+#define CFE_INIT_SAFE 0x00010000 /* "Safe mode" */
+#define CFE_INIT_PCI 0x00020000 /* Initialize PCI */
+#define CFE_LDT_SLAVE 0x00040000 /* Select LDT slave mode */
+
+/* *********************************************************************
+ * Other constants
+ ********************************************************************* */
+
+#define CFE_MAX_HANDLE 64 /* max file handles */
+
+#if !defined(__ASSEMBLER__)
+
+/* *********************************************************************
+ * prototypes
+ ********************************************************************* */
+
+void board_console_init(void);
+void board_device_init(void);
+void board_final_init(void);
+void board_device_reset(void);
+#define CFE_BUFFER_CONSOLE "buffer"
+int cfe_set_console(char *);
+int cfe_set_envdevice(char *);
+void cfe_restart(void);
+void cfe_command_loop(void);
+void cfe_leds(unsigned int val);
+void cfe_ledstr(const char *str);
+void cfe_launch(unsigned long ept);
+void cfe_start(unsigned long ept);
+void cfe_warmstart(unsigned long long);
+#define SETLEDS(x) cfe_ledstr(x)
+const char *cfe_errortext(int err);
+
+#endif
diff --git a/cfe/cfe/include/cfe_autoboot.h b/cfe/cfe/include/cfe_autoboot.h
new file mode 100644
index 0000000..603803b
--- /dev/null
+++ b/cfe/cfe/include/cfe_autoboot.h
@@ -0,0 +1,71 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Automatic OS bootstrap File: cfe_autoboot.h
+ *
+ * This module handles OS bootstrap stuff. We use this version
+ * to do "automatic" booting; walking down a list of possible boot
+ * options, trying them until something good happens.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#define CFE_AUTOBOOT_END 0
+#define CFE_AUTOBOOT_NETWORK 1
+#define CFE_AUTOBOOT_DISK 2
+#define CFE_AUTOBOOT_RAW 3
+
+typedef struct cfe_autoboot_method_s {
+ queue_t ab_qblock;
+ int ab_type;
+ int ab_flags;
+ char *ab_dev;
+ char *ab_loader;
+ char *ab_filesys;
+ char *ab_file;
+} cfe_autoboot_method_t;
+
+#define CFE_AUTOFLG_POLLCONSOLE 1 /* boot can be interrupted */
+#define CFE_AUTOFLG_TRYFOREVER 2 /* keep trying forever */
+
+int cfe_autoboot(char *dev,int flags);
+int cfe_add_autoboot(int type,int flags,char *dev,char *loader,char *filesys,char *file);
+
+
diff --git a/cfe/cfe/include/cfe_boot.h b/cfe/cfe/include/cfe_boot.h
new file mode 100644
index 0000000..93c3c6d
--- /dev/null
+++ b/cfe/cfe/include/cfe_boot.h
@@ -0,0 +1,58 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Bootstrap prototypes File: cfe_boot.h
+ *
+ * Prototypes for main bootstrap routines
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define BOOT_START_ADDRESS 0x20000000 /* VA of boot area */
+#define BOOT_AREA_SIZE (256*1024) /* 256K */
+
+
+
+
diff --git a/cfe/cfe/include/cfe_bootblock.h b/cfe/cfe/include/cfe_bootblock.h
new file mode 100644
index 0000000..c3a93f0
--- /dev/null
+++ b/cfe/cfe/include/cfe_bootblock.h
@@ -0,0 +1,129 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Boot Block File: cfe_bootblock.h
+ *
+ * The structure of the boot block used on block-style devices
+ * like disks and CDROMs
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+/*
+ * CFE boot block, modeled loosely on Alpha.
+ *
+ * It consists of:
+ *
+ * BSD disk label
+ * <blank space>
+ * Boot block info (5 u_int_64s)
+ *
+ * The boot block portion looks like:
+ *
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * | BOOT_MAGIC_NUMBER |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * | Flags | Reserved | Vers | Header Checksum |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * | Secondary Loader Location (bytes) |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * | Loader Checksum | Size of loader (bytes) |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * | Reserved | Architecture Information |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * Boot block fields should always be read as 64-bit numbers.
+ *
+ */
+
+
+struct boot_block {
+ uint64_t bb_data[64]; /* data (disklabel, also as below) */
+};
+#define bb_magic bb_data[59] /* magic number */
+#define bb_hdrinfo bb_data[60] /* header checksum, ver, flags */
+#define bb_secstart bb_data[61] /* secondary start (bytes) */
+#define bb_secsize bb_data[62] /* secondary size (bytes) */
+#define bb_archinfo bb_data[63] /* architecture info */
+
+#define BOOT_BLOCK_OFFSET 0 /* offset of boot block. */
+#define BOOT_BLOCK_BLOCKSIZE 512 /* block size for sec. size/start,
+ * and for boot block itself
+ */
+#define BOOT_BLOCK_SIZE 40 /* 5 64-bit words */
+
+/*
+ * This is the highest block number that we look at when
+ * searching for a valid boot block
+ */
+#define BOOT_BLOCK_MAXLOC 16
+
+/*
+ * Fields within the boot block
+ */
+#define _U64(x) ((uint64_t) x)
+#define BOOT_MAGIC_NUMBER _U64(0x43465631424f4f54)
+#define BOOT_HDR_CHECKSUM_MASK _U64(0x00000000FFFFFFFF)
+#define BOOT_HDR_VER_MASK _U64(0x000000FF00000000)
+#define BOOT_HDR_VER_SHIFT 32
+#define BOOT_HDR_FLAGS_MASK _U64(0xFF00000000000000)
+#define BOOT_SECSIZE_MASK _U64(0x00000000FFFFFFFF)
+#define BOOT_DATA_CHECKSUM_MASK _U64(0xFFFFFFFF00000000)
+#define BOOT_DATA_CHECKSUM_SHIFT 32
+#define BOOT_ARCHINFO_MASK _U64(0x00000000FFFFFFFF)
+
+#define BOOT_HDR_VERSION 1
+
+#define CHECKSUM_BOOT_DATA(data,len,cksum) \
+ do { \
+ uint32_t *_ptr = (uint32_t *) (data); \
+ uint32_t _cksum; \
+ int _i; \
+ \
+ _cksum = 0; \
+ for (_i = 0; \
+ _i < ((len) / sizeof (uint32_t)); \
+ _i++) \
+ _cksum += _ptr[_i]; \
+ *(cksum) = _cksum; \
+ } while (0)
+
+
diff --git a/cfe/cfe/include/cfe_console.h b/cfe/cfe/include/cfe_console.h
new file mode 100755
index 0000000..7ee1056
--- /dev/null
+++ b/cfe/cfe/include/cfe_console.h
@@ -0,0 +1,92 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Console prototypes File: cfe_console.c
+ *
+ * Prototypes for routines dealing with the console.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define VKEY(x) (0x100|(x))
+#define VKEY_UP VKEY(1)
+#define VKEY_DOWN VKEY(2)
+#define VKEY_LEFT VKEY(3)
+#define VKEY_RIGHT VKEY(4)
+#define VKEY_PGUP VKEY(5)
+#define VKEY_PGDN VKEY(6)
+#define VKEY_HOME VKEY(7)
+#define VKEY_END VKEY(8)
+#define VKEY_F1 VKEY(0x10)
+#define VKEY_F2 VKEY(0x11)
+#define VKEY_F3 VKEY(0x12)
+#define VKEY_F4 VKEY(0x13)
+#define VKEY_F5 VKEY(0x14)
+#define VKEY_F6 VKEY(0x15)
+#define VKEY_F7 VKEY(0x16)
+#define VKEY_F8 VKEY(0x17)
+#define VKEY_F9 VKEY(0x18)
+#define VKEY_F10 VKEY(0x19)
+#define VKEY_F11 VKEY(0x1A)
+#define VKEY_F12 VKEY(0x1B)
+#define VKEY_ESC 27
+
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+int console_open(char *name);
+int console_close(void);
+int console_read(char *buffer,int length);
+int console_write(char *buffer,int length);
+int console_status(void);
+int console_readkey(void);
+int console_readline(char *prompt,char *str,int len);
+int console_readline_noedit(char *prompt,char *str,int len);
+int console_readline(char *prompt,char *str,int len);
+extern char *console_name;
+extern int console_handle;
+void console_log(const char *tmplt,...);
+
+
diff --git a/cfe/cfe/include/cfe_devfuncs.h b/cfe/cfe/include/cfe_devfuncs.h
new file mode 100644
index 0000000..207c4a6
--- /dev/null
+++ b/cfe/cfe/include/cfe_devfuncs.h
@@ -0,0 +1,76 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Device function prototypes File: cfe_devfuncs.h
+ *
+ * This module contains prototypes for cfe_devfuncs.c, a set
+ * of wrapper routines to the IOCB interface. This file,
+ * along with cfe_devfuncs.c, can be incorporated into programs
+ * that need to call CFE.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#define CFE_EPTSEAL 0x43464531
+#if (CFG_BIENDIAN) && defined(__MIPSEB)
+#define CFE_EPTSEAL_REV 0x31454643
+#endif
+
+#define CFE_APISEAL 0xBFC004E0
+#define CFE_APIENTRY 0xBFC00500
+
+
+
+#ifndef __ASSEMBLER__
+int cfe_open(char *name);
+int cfe_close(int handle);
+int cfe_readblk(int handle,cfe_offset_t offset,unsigned char *buffer,int length);
+int cfe_read(int handle,unsigned char *buffer,int length);
+int cfe_writeblk(int handle,cfe_offset_t offset,unsigned char *buffer,int length);
+int cfe_write(int handle,unsigned char *buffer,int length);
+int cfe_ioctl(int handle,unsigned int ioctlnum,unsigned char *buffer,int length,int *retlen,
+ cfe_offset_t offset);
+int cfe_inpstat(int handle);
+int cfe_getenv(char *name,char *dest,int destlen);
+long long cfe_getticks(void);
+int cfe_exit(int warm,int code);
+int cfe_flushcache(int flg);
+int cfe_getdevinfo(char *name);
+int cfe_flushcache(int);
+#endif
diff --git a/cfe/cfe/include/cfe_device.h b/cfe/cfe/include/cfe_device.h
new file mode 100644
index 0000000..f90b167
--- /dev/null
+++ b/cfe/cfe/include/cfe_device.h
@@ -0,0 +1,118 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Device manager definitions File: cfe_device.h
+ *
+ * Structures, constants, etc. for the device manager, which keeps
+ * track of installed devices in CFE.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#ifndef _CFE_DEVICE_H
+#define _CFE_DEVICE_H
+
+#include "lib_queue.h"
+
+typedef struct cfe_devdisp_s cfe_devdisp_t;
+
+
+/*
+ * The Device structure defines a particular instance of a device.
+ * They are generated as a result of calling the cfe_attach call.
+ */
+
+typedef struct cfe_device_s {
+ queue_t dev_next;
+ char *dev_fullname;
+ void *dev_softc;
+ int dev_class;
+ const cfe_devdisp_t *dev_dispatch;
+ int dev_opencount;
+ char *dev_description;
+} cfe_device_t;
+
+/*
+ * This is what gets returned from the OPEN call
+ */
+typedef struct cfe_devctx_s {
+ cfe_device_t *dev_dev;
+ void *dev_softc;
+ void *dev_openinfo;
+} cfe_devctx_t;
+
+
+/*
+ * This defines a given device class. Even though there are
+ * three identical MACs, there is only one of these.
+ */
+
+struct cfe_devdisp_s {
+ int (*dev_open)(cfe_devctx_t *ctx);
+ int (*dev_read)(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+ int (*dev_inpstat)(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+ int (*dev_write)(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+ int (*dev_ioctl)(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+ int (*dev_close)(cfe_devctx_t *ctx);
+ void (*dev_poll)(cfe_devctx_t *ctx,int64_t ticks);
+ void (*dev_reset)(void *softc); /* called when device is closed, so no devctx_t */
+};
+
+
+
+typedef struct cfe_driver_s {
+ char *drv_description; /* Description of device for SHOW commands */
+ char *drv_bootname; /* Device's name prefix for open() */
+ int drv_class;
+ const cfe_devdisp_t *drv_dispatch;
+ void (*drv_probe)(struct cfe_driver_s *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+} cfe_driver_t;
+
+char *cfe_device_name(cfe_devctx_t *ctx);
+void cfe_attach(cfe_driver_t *devname,void *softc,char *bootinfo,char *description);
+int cfe_attach_idx(cfe_driver_t *drv,int idx,void *softc,char *bootinfo,char *description);
+cfe_device_t *cfe_finddev(char *name);
+void cfe_attach_init(void);
+#define cfe_add_device(devdescr,a,b,ptr) (devdescr)->drv_probe(devdescr,a,b,ptr)
+void cfe_device_reset(void);
+
+#endif
diff --git a/cfe/cfe/include/cfe_error.h b/cfe/cfe/include/cfe_error.h
new file mode 100644
index 0000000..9c564e1
--- /dev/null
+++ b/cfe/cfe/include/cfe_error.h
@@ -0,0 +1,110 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Error codes File: cfe_error.h
+ *
+ * CFE's global error code list is here.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+
+#define CFE_OK 0
+#define CFE_ERR -1 /* generic error */
+#define CFE_ERR_INV_COMMAND -2
+#define CFE_ERR_EOF -3
+#define CFE_ERR_IOERR -4
+#define CFE_ERR_NOMEM -5
+#define CFE_ERR_DEVNOTFOUND -6
+#define CFE_ERR_DEVOPEN -7
+#define CFE_ERR_INV_PARAM -8
+#define CFE_ERR_ENVNOTFOUND -9
+#define CFE_ERR_ENVREADONLY -10
+
+#define CFE_ERR_NOTELF -11
+#define CFE_ERR_NOT32BIT -12
+#define CFE_ERR_WRONGENDIAN -13
+#define CFE_ERR_BADELFVERS -14
+#define CFE_ERR_NOTMIPS -15
+#define CFE_ERR_BADELFFMT -16
+#define CFE_ERR_BADADDR -17
+
+#define CFE_ERR_FILENOTFOUND -18
+#define CFE_ERR_UNSUPPORTED -19
+
+#define CFE_ERR_HOSTUNKNOWN -20
+
+#define CFE_ERR_TIMEOUT -21
+
+#define CFE_ERR_PROTOCOLERR -22
+
+#define CFE_ERR_NETDOWN -23
+#define CFE_ERR_NONAMESERVER -24
+
+#define CFE_ERR_NOHANDLES -25
+#define CFE_ERR_ALREADYBOUND -26
+
+#define CFE_ERR_CANNOTSET -27
+#define CFE_ERR_NOMORE -28
+#define CFE_ERR_BADFILESYS -29
+#define CFE_ERR_FSNOTAVAIL -30
+
+#define CFE_ERR_INVBOOTBLOCK -31
+#define CFE_ERR_WRONGDEVTYPE -32
+#define CFE_ERR_BBCHECKSUM -33
+#define CFE_ERR_BOOTPROGCHKSUM -34
+
+#define CFE_ERR_LDRNOTAVAIL -35
+
+#define CFE_ERR_NOTREADY -36
+
+#define CFE_ERR_GETMEM -37
+#define CFE_ERR_SETMEM -38
+
+#define CFE_ERR_NOTCONN -39
+#define CFE_ERR_ADDRINUSE -40
+
+/* Foxconn add start by Cliff Wang, 03/23/2010 */
+#define CFE_ERR_INTR -41
+#define CFE_ERR_BADIMAGE -42
+/* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+
diff --git a/cfe/cfe/include/cfe_fileops.h b/cfe/cfe/include/cfe_fileops.h
new file mode 100644
index 0000000..f119037
--- /dev/null
+++ b/cfe/cfe/include/cfe_fileops.h
@@ -0,0 +1,109 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Filesystem dispatch defs File: cfe_fileops.h
+ *
+ * CFE supports multiple access methods to files on boot
+ * media. This module contains the dispatch table structures
+ * for "file systems".
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define FILE_SEEK_BEGINNING 0
+#define FILE_SEEK_CURRENT 1
+
+#define FILE_MODE_READ 1
+#define FILE_MODE_WRITE 2
+
+/* These flags should not conflict with the loader arg flags (see cfe_loadargs_t) */
+#define FSYS_TYPE_NETWORK 0x40000000
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define BDINIT(ops,fsctx,name) (ops)->init((fsctx),(name))
+#define BDOPEN(ops,ref,fsctx,name) (ops)->open((ref),(fsctx),(name),FILE_MODE_READ)
+#define BDOPEN2(ops,ref,fsctx,name,mode) (ops)->open((ref),(fsctx),(name),(mode))
+#define BDOPEN_WR(ops,ref,fsctx,name) (ops)->open((ref),(fsctx),(name),FILE_MODE_WRITE)
+#define BDREAD(ops,ref,buf,len) (ops)->read((ref),(buf),(len))
+#define BDWRITE(ops,ref,buf,len) (ops)->write((ref),(buf),(len))
+#define BDCLOSE(ops,ref) (ops)->close((ref))
+#define BDUNINIT(ops,ref) (ops)->uninit((ref))
+#define BDSEEK(ops,ref,offset,how) (ops)->seek((ref),(offset),(how))
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef struct fileio_dispatch_s {
+ const char *method;
+ unsigned int loadflags;
+ int (*init)(void **fsctx,void *device);
+ int (*open)(void **ref,void *fsctx,char *filename,int mode);
+ int (*read)(void *ref,uint8_t *buf,int len);
+ int (*write)(void *ref,uint8_t *buf,int len);
+ int (*seek)(void *ref,int offset,int how);
+ void (*close)(void *ref);
+ void (*uninit)(void *devctx);
+} fileio_dispatch_t;
+
+typedef struct fileio_ctx_s {
+ const fileio_dispatch_t *ops;
+ void *fsctx;
+} fileio_ctx_t;
+
+const fileio_dispatch_t *cfe_findfilesys(const char *name);
+
+int fs_init(char *fsname,fileio_ctx_t **fsctx,void *device);
+int fs_uninit(fileio_ctx_t *);
+int fs_open(fileio_ctx_t *,void **ref,char *filename,int mode);
+int fs_close(fileio_ctx_t *,void *ref);
+int fs_read(fileio_ctx_t *,void *ref,uint8_t *buffer,int len);
+int fs_write(fileio_ctx_t *,void *ref,uint8_t *buffer,int len);
+int fs_seek(fileio_ctx_t *,void *ref,int offset,int how);
+int fs_hook(fileio_ctx_t *fsctx,char *fsname);
+
+
diff --git a/cfe/cfe/include/cfe_flashimage.h b/cfe/cfe/include/cfe_flashimage.h
new file mode 100644
index 0000000..4e4647c
--- /dev/null
+++ b/cfe/cfe/include/cfe_flashimage.h
@@ -0,0 +1,64 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Flash Image defs File: cfe_flashimage.h
+ *
+ * This file contains stuff that describes the image header on
+ * the front of our flash images.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+typedef struct cfe_flashimage_s {
+ uint8_t seal[4]; /* CFE1 */
+ uint8_t flags[4]; /* Various flags, always big-endian */
+ uint8_t size[4]; /* Image size, in bytes, always big-endian */
+ uint8_t crc[4]; /* CRC-32, always big-endian */
+ uint8_t boardname[32]; /* Board name */
+ uint8_t majver,minver,ecover,miscver; /* Firmware version */
+ uint8_t reserved[12]; /* not used just yet */
+} cfe_flashimage_t; /* should be 64 bytes */
+
+
+#define CFE_IMAGE_SEAL "CFE1"
+#define CFE_IMAGE_EB 0x00000001
+#define CFE_IMAGE_EL 0x00000002
+#define CFE_IMAGE_MLONG64 0x00000004
+
diff --git a/cfe/cfe/include/cfe_iocb.h b/cfe/cfe/include/cfe_iocb.h
new file mode 100644
index 0000000..bc62078
--- /dev/null
+++ b/cfe/cfe/include/cfe_iocb.h
@@ -0,0 +1,211 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * IOCB definitions File: cfe_iocb.h
+ *
+ * This module describes CFE's IOCB structure, the main
+ * data structure used to communicate API requests with CFE.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifndef _CFE_IOCB_H
+#define _CFE_IOCB_H
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define CFE_CMD_FW_GETINFO 0
+#define CFE_CMD_FW_RESTART 1
+#define CFE_CMD_FW_BOOT 2
+#define CFE_CMD_FW_CPUCTL 3
+#define CFE_CMD_FW_GETTIME 4
+#define CFE_CMD_FW_MEMENUM 5
+#define CFE_CMD_FW_FLUSHCACHE 6
+
+#define CFE_CMD_DEV_GETHANDLE 9
+#define CFE_CMD_DEV_ENUM 10
+#define CFE_CMD_DEV_OPEN 11
+#define CFE_CMD_DEV_INPSTAT 12
+#define CFE_CMD_DEV_READ 13
+#define CFE_CMD_DEV_WRITE 14
+#define CFE_CMD_DEV_IOCTL 15
+#define CFE_CMD_DEV_CLOSE 16
+#define CFE_CMD_DEV_GETINFO 17
+
+#define CFE_CMD_ENV_ENUM 20
+#define CFE_CMD_ENV_GET 22
+#define CFE_CMD_ENV_SET 23
+#define CFE_CMD_ENV_DEL 24
+
+#define CFE_CMD_MAX 32
+
+#define CFE_CMD_VENDOR_USE 0x8000 /* codes above this are for customer use */
+
+#define CFE_MI_RESERVED 0 /* memory is reserved, do not use */
+#define CFE_MI_AVAILABLE 1 /* memory is available */
+
+#define CFE_FLG_WARMSTART 0x00000001
+#define CFE_FLG_FULL_ARENA 0x00000001
+#define CFE_FLG_ENV_PERMANENT 0x00000001
+
+#define CFE_CPU_CMD_START 1
+#define CFE_CPU_CMD_STOP 0
+
+#define CFE_STDHANDLE_CONSOLE 0
+
+#define CFE_DEV_NETWORK 1
+#define CFE_DEV_DISK 2
+#define CFE_DEV_FLASH 3
+#define CFE_DEV_SERIAL 4
+#define CFE_DEV_CPU 5
+#define CFE_DEV_NVRAM 6
+#define CFE_DEV_CLOCK 7
+#define CFE_DEV_OTHER 8
+#define CFE_DEV_MASK 0x0F
+
+#define CFE_CACHE_FLUSH_D 1
+#define CFE_CACHE_INVAL_I 2
+#define CFE_CACHE_INVAL_D 4
+#define CFE_CACHE_INVAL_L2 8
+#define CFE_CACHE_FLUSH_L2 16
+#define CFE_CACHE_INVAL_RANGE 32
+#define CFE_CACHE_FLUSH_RANGE 64
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+#define unsigned signed /* Kludge to get unsigned size-shaped type. */
+typedef __SIZE_TYPE__ cfe_int_t;
+#undef unsigned
+typedef __SIZE_TYPE__ cfe_uint_t;
+typedef unsigned long long cfe_offset_t;
+typedef long long cfe_int64_t;
+typedef unsigned char *cfe_ptr_t;
+
+typedef struct iocb_buffer_s {
+ cfe_offset_t buf_offset; /* offset on device (bytes) */
+ cfe_ptr_t buf_ptr; /* pointer to a buffer */
+ cfe_uint_t buf_length; /* length of this buffer */
+ cfe_uint_t buf_retlen; /* returned length (for read ops) */
+ cfe_uint_t buf_ioctlcmd; /* IOCTL command (used only for IOCTLs) */
+} iocb_buffer_t;
+
+#define buf_devflags buf_ioctlcmd /* returned device info flags */
+
+typedef struct iocb_inpstat_s {
+ cfe_uint_t inp_status; /* 1 means input available */
+} iocb_inpstat_t;
+
+typedef struct iocb_envbuf_s {
+ int enum_idx; /* 0-based enumeration index */
+ cfe_ptr_t name_ptr; /* name string buffer */
+ cfe_int_t name_length; /* size of name buffer */
+ cfe_ptr_t val_ptr; /* value string buffer */
+ cfe_int_t val_length; /* size of value string buffer */
+} iocb_envbuf_t;
+
+typedef struct iocb_cpuctl_s {
+ cfe_uint_t cpu_number; /* cpu number to control */
+ cfe_uint_t cpu_command; /* command to issue to CPU */
+ cfe_uint_t start_addr; /* CPU start address */
+ cfe_uint_t gp_val; /* starting GP value */
+ cfe_uint_t sp_val; /* starting SP value */
+ cfe_uint_t a1_val; /* starting A1 value */
+} iocb_cpuctl_t;
+
+typedef struct iocb_time_s {
+ long long ticks; /* current time in ticks */
+} iocb_time_t;
+
+typedef struct iocb_exitstat_s {
+ cfe_int_t status;
+} iocb_exitstat_t;
+
+typedef struct iocb_meminfo_s {
+ cfe_int_t mi_idx; /* 0-based enumeration index */
+ cfe_int_t mi_type; /* type of memory block */
+ cfe_int64_t mi_addr; /* physical start address */
+ cfe_int64_t mi_size; /* block size */
+} iocb_meminfo_t;
+
+#define CFE_FWI_64BIT 0x00000001
+#define CFE_FWI_32BIT 0x00000002
+#define CFE_FWI_RELOC 0x00000004
+#define CFE_FWI_UNCACHED 0x00000008
+#define CFE_FWI_MULTICPU 0x00000010
+#define CFE_FWI_FUNCSIM 0x00000020
+#define CFE_FWI_RTLSIM 0x00000040
+
+typedef struct iocb_fwinfo_s {
+ cfe_int64_t fwi_version; /* major, minor, eco version */
+ cfe_int64_t fwi_totalmem; /* total installed mem */
+ cfe_int64_t fwi_flags; /* various flags */
+ cfe_int64_t fwi_boardid; /* board ID */
+ cfe_int64_t fwi_bootarea_va; /* VA of boot area */
+ cfe_int64_t fwi_bootarea_pa; /* PA of boot area */
+ cfe_int64_t fwi_bootarea_size; /* size of boot area */
+ cfe_int64_t fwi_reserved1;
+ cfe_int64_t fwi_reserved2;
+ cfe_int64_t fwi_reserved3;
+} iocb_fwinfo_t;
+
+
+typedef struct cfe_iocb_s {
+ cfe_uint_t iocb_fcode; /* IOCB function code */
+ cfe_int_t iocb_status; /* return status */
+ cfe_int_t iocb_handle; /* file/device handle */
+ cfe_uint_t iocb_flags; /* flags for this IOCB */
+ cfe_uint_t iocb_psize; /* size of parameter list */
+ union {
+ iocb_buffer_t iocb_buffer; /* buffer parameters */
+ iocb_inpstat_t iocb_inpstat; /* input status parameters */
+ iocb_envbuf_t iocb_envbuf; /* environment function parameters */
+ iocb_cpuctl_t iocb_cpuctl; /* CPU control parameters */
+ iocb_time_t iocb_time; /* timer parameters */
+ iocb_meminfo_t iocb_meminfo; /* memory arena info parameters */
+ iocb_fwinfo_t iocb_fwinfo; /* firmware information */
+ iocb_exitstat_t iocb_exitstat; /* Exit Status */
+ } plist;
+} cfe_iocb_t;
+
+
+#endif
diff --git a/cfe/cfe/include/cfe_ioctl.h b/cfe/cfe/include/cfe_ioctl.h
new file mode 100644
index 0000000..1a389f8
--- /dev/null
+++ b/cfe/cfe/include/cfe_ioctl.h
@@ -0,0 +1,167 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * IOCTL definitions File: cfe_ioctl.h
+ *
+ * IOCTL function numbers and I/O data structures.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+/* *********************************************************************
+ * NVFAM and FLASH stuff
+ ********************************************************************* */
+
+#define IOCTL_NVRAM_GETINFO 1 /* return nvram_info_t */
+#define IOCTL_NVRAM_ERASE 2 /* erase sector containing nvram_info_t area */
+#define IOCTL_FLASH_ERASE_SECTOR 3 /* erase an arbitrary sector */
+#define IOCTL_FLASH_ERASE_ALL 4 /* Erase the entire flash */
+#define IOCTL_FLASH_WRITE_ALL 5 /* write entire flash */
+#define IOCTL_FLASH_GETINFO 6 /* get flash device info */
+#define IOCTL_FLASH_GETSECTORS 7 /* get sector information */
+#define IOCTL_FLASH_ERASE_RANGE 8 /* erase range of bytes */
+#define IOCTL_NVRAM_UNLOCK 9 /* allow r/w beyond logical end of device */
+#define IOCTL_FLASH_PROTECT_RANGE 10 /* Protect a group of sectors */
+#define IOCTL_FLASH_UNPROTECT_RANGE 11 /* unprotect a group of sectors */
+#define IOCTL_FLASH_DATA_WIDTH_MODE 12 /* switch flash and gen bus to support 8 or 16-bit mode I/Os */
+#define IOCTL_FLASH_BURST_MODE 13 /* configure gen bus for burst mode */
+
+typedef struct flash_range_s {
+ unsigned int range_base;
+ unsigned int range_length;
+} flash_range_t;
+
+typedef struct flash_info_s {
+ unsigned long long flash_base; /* flash physical base address */
+ unsigned int flash_size; /* available device size in bytes */
+ unsigned int flash_type; /* type, from FLASH_TYPE below */
+ unsigned int flash_flags; /* Various flags (FLASH_FLAG_xxx) */
+} flash_info_t;
+
+typedef struct flash_sector_s {
+ int flash_sector_idx;
+ int flash_sector_status;
+ unsigned int flash_sector_offset;
+ unsigned int flash_sector_size;
+} flash_sector_t;
+
+#define FLASH_SECTOR_OK 0
+#define FLASH_SECTOR_INVALID -1
+
+#define FLASH_TYPE_UNKNOWN 0 /* not sure what kind of flash */
+#define FLASH_TYPE_SRAM 1 /* not flash: it's SRAM */
+#define FLASH_TYPE_ROM 2 /* not flash: it's ROM */
+#define FLASH_TYPE_FLASH 3 /* it's flash memory of some sort */
+
+#define FLASH_FLAG_NOERASE 1 /* Byte-range writes supported,
+ Erasing is not necessary */
+
+typedef struct nvram_info_s {
+ int nvram_offset; /* offset of environment area */
+ int nvram_size; /* size of environment area */
+ int nvram_eraseflg; /* true if we need to erase first */
+} nvram_info_t;
+
+/* *********************************************************************
+ * Ethernet stuff
+ ********************************************************************* */
+
+#define IOCTL_ETHER_GETHWADDR 1 /* Get hardware address (6bytes) */
+#define IOCTL_ETHER_SETHWADDR 2 /* Set hardware address (6bytes) */
+#define IOCTL_ETHER_GETSPEED 3 /* Get Speed and Media (int) */
+#define IOCTL_ETHER_SETSPEED 4 /* Set Speed and Media (int) */
+#define IOCTL_ETHER_GETLINK 5 /* get link status (int) */
+#define IOCTL_ETHER_GETLOOPBACK 7 /* get loopback state */
+#define IOCTL_ETHER_SETLOOPBACK 8 /* set loopback state */
+#define IOCTL_ETHER_SETPACKETFIFO 9 /* set packet fifo mode (int) */
+#define IOCTL_ETHER_SETSTROBESIG 10 /* set strobe signal (int) */
+
+#define ETHER_LOOPBACK_OFF 0 /* no loopback */
+#define ETHER_LOOPBACK_INT 1 /* Internal loopback */
+#define ETHER_LOOPBACK_EXT 2 /* External loopback (through PHY) */
+
+#define ETHER_SPEED_AUTO 0 /* Auto detect */
+#define ETHER_SPEED_UNKNOWN 0 /* Speed not known (on link status) */
+#define ETHER_SPEED_10HDX 1 /* 10MB hdx and fdx */
+#define ETHER_SPEED_10FDX 2
+#define ETHER_SPEED_100HDX 3 /* 100MB hdx and fdx */
+#define ETHER_SPEED_100FDX 4
+#define ETHER_SPEED_1000HDX 5 /* 1000MB hdx and fdx */
+#define ETHER_SPEED_1000FDX 6
+
+#define ETHER_FIFO_8 0 /* 8-bit packet fifo mode */
+#define ETHER_FIFO_16 1 /* 16-bit packet fifo mode */
+#define ETHER_ETHER 2 /* Standard ethernet mode */
+
+#define ETHER_STROBE_GMII 0 /* GMII style strobe signal */
+#define ETHER_STROBE_ENCODED 1 /* Encoded */
+#define ETHER_STROBE_SOP 2 /* SOP flagged. Only in 8-bit mode*/
+#define ETHER_STROBE_EOP 3 /* EOP flagged. Only in 8-bit mode*/
+
+/* *********************************************************************
+ * Serial Ports
+ ********************************************************************* */
+
+#define IOCTL_SERIAL_SETSPEED 1 /* get baud rate (int) */
+#define IOCTL_SERIAL_GETSPEED 2 /* set baud rate (int) */
+#define IOCTL_SERIAL_SETFLOW 3 /* Set Flow Control */
+#define IOCTL_SERIAL_GETFLOW 4 /* Get Flow Control */
+
+#define SERIAL_FLOW_NONE 0 /* no flow control */
+#define SERIAL_FLOW_SOFTWARE 1 /* software flow control (not impl) */
+#define SERIAL_FLOW_HARDWARE 2 /* hardware flow control */
+
+/* *********************************************************************
+ * Block device stuff
+ ********************************************************************* */
+
+#define IOCTL_BLOCK_GETBLOCKSIZE 1 /* get block size (int) */
+#define IOCTL_BLOCK_GETTOTALBLOCKS 2 /* get total bocks (long long) */
+#define IOCTL_BLOCK_GETDEVTYPE 3 /* get device type (struct) */
+
+typedef struct blockdev_info_s {
+ unsigned long long blkdev_totalblocks;
+ unsigned int blkdev_blocksize;
+ unsigned int blkdev_devtype;
+} blockdev_info_t;
+
+#define BLOCK_DEVTYPE_DISK 0
+#define BLOCK_DEVTYPE_CDROM 1
+
diff --git a/cfe/cfe/include/cfe_irq.h b/cfe/cfe/include/cfe_irq.h
new file mode 100644
index 0000000..7605b5e
--- /dev/null
+++ b/cfe/cfe/include/cfe_irq.h
@@ -0,0 +1,103 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * IRQ related definitions File: cfe_irq.h
+ *
+ * This module describes CFE's interface for dispatching
+ * to driver-supplied service routines. Dispatch can be based
+ * either on asynchronous interrupt events or on synchrnous
+ * polling of the interrupt status registers from the idle loop.
+ *
+ * The interface attempts to accomodate the concept of interrupt
+ * mapping as is common on high-integration parts with standard
+ * cores. The details are motivated by the bcm1250/MIPS
+ * architecture, where the mapping abstraction is somewhat violated
+ * by CP0 interrupts that do not go through the mapper.
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define NR_IRQS 64
+
+#define CFE_IRQ_FLAGS_SHARED 0x1
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+/* *********************************************************************
+ * Functions
+ ********************************************************************* */
+
+void cfe_irq_init(void);
+
+
+/* Functions that use interrupt mapping, i.e., the irq argument is the
+ interrupt number at the input to the mapper. */
+
+void cfe_mask_irq(int cpu, unsigned int irq);
+void cfe_unmask_irq(int cpu, unsigned int irq);
+
+void cfe_enable_irq(unsigned int irq);
+void cfe_disable_irq(unsigned int irq);
+
+int cfe_request_irq(unsigned int irq,
+ void (*handler)(void *), void *arg,
+ unsigned long irqflags, int device);
+void cfe_free_irq(unsigned int irq, int device);
+
+/* pseudo-interrupts, by polling request lines and invoking handlers */
+
+void cfe_irq_poll(void *);
+
+
+/* Functions that bypass interrupt mapping, i.e., the ip argument
+ is the interrupt number at the output of the mapper and/or the
+ input to the CPU. */
+
+typedef void (* ip_handler_t)(int ip);
+
+void cfe_irq_setvector(int ip, ip_handler_t handler);
+
+/* enable/disable interrupts at the CPU level. */
+
+void cfe_irq_enable(int mask);
+int cfe_irq_disable(void);
diff --git a/cfe/cfe/include/cfe_loader.h b/cfe/cfe/include/cfe_loader.h
new file mode 100644
index 0000000..9ed0c13
--- /dev/null
+++ b/cfe/cfe/include/cfe_loader.h
@@ -0,0 +1,86 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Loader API File: cfe_loader.h
+ *
+ * This is the main API for the program loader.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifndef _CFE_LOADER_H_
+#define _CFE_LOADER_H_
+
+#define LOADFLG_NOISY 0x0001 /* print out noisy info */
+#define LOADFLG_EXECUTE 0x0002 /* execute loaded program */
+#define LOADFLG_SPECADDR 0x0004 /* Use a specific size & addr */
+#define LOADFLG_NOBB 0x0008 /* don't look for a boot block */
+#define LOADFLG_NOCLOSE 0x0010 /* don't close network */
+#define LOADFLG_COMPRESSED 0x0020 /* file is compressed */
+#define LOADFLG_BATCH 0x0040 /* batch file */
+
+typedef struct cfe_loadargs_s {
+ char *la_filename; /* name of file on I/O device */
+ char *la_filesys; /* file system name */
+ char *la_device; /* device name (ide0, etc.) */
+ char *la_options; /* args to pass to loaded prog */
+ char *la_loader; /* binary file loader to use */
+ unsigned int la_flags; /* various flags */
+ long la_address; /* used by SPECADDR only */
+ unsigned long la_maxsize; /* used by SPECADDR only */
+ long la_entrypt; /* returned entry point */
+} cfe_loadargs_t;
+
+
+typedef struct cfe_loader_s {
+ char *name; /* name of loader */
+ int (*loader)(cfe_loadargs_t *); /* access function */
+ int flags; /* flags */
+} cfe_loader_t;
+
+#define LDRLOAD(ldr,arg) (*((ldr)->loader))(arg)
+
+int cfe_load_program(char *name,cfe_loadargs_t *la);
+const cfe_loader_t *cfe_findloader(char *name);
+void splitpath(char *path,char **devname,char **filename);
+void cfe_go(cfe_loadargs_t *la);
+int cfe_boot(char *ldrname,cfe_loadargs_t *la);
+int cfe_savedata(char *fsname,char *devname,char *filename,uint8_t *start,uint8_t *end);
+
+#endif /* _CFE_LOADER_H_ */
diff --git a/cfe/cfe/include/cfe_mem.h b/cfe/cfe/include/cfe_mem.h
new file mode 100644
index 0000000..83c3be2
--- /dev/null
+++ b/cfe/cfe/include/cfe_mem.h
@@ -0,0 +1,79 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Memory manager definitions File: cfe_mem.h
+ *
+ * Function prototypes and contants for the memory manager
+ * (used to manage the physical memory arena)
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define MEMTYPE_EMPTY 0
+#define MEMTYPE_DRAM_AVAILABLE 1 /* must match value in cfe_iocb.h */
+#define MEMTYPE_DRAM_NOTINSTALLED 2
+#define MEMTYPE_DRAM_USEDBYFIRMWARE 3
+#define MEMTYPE_BOOTROM 4
+#define MEMTYPE_IOREGISTERS 5
+#define MEMTYPE_RESERVED 6
+#define MEMTYPE_L2CACHE 7
+#define MEMTYPE_LDT_PCI 8
+#define MEMTYPE_DRAM_BOOTPROGRAM 9
+
+/* *********************************************************************
+ * External data
+ ********************************************************************* */
+
+extern unsigned int mem_bootarea_start;
+extern unsigned int mem_bootarea_size;
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+void cfe_arena_init(void);
+int cfe_arena_loadcheck(uintptr_t start,unsigned int size);
+int cfe_arena_enum(int idx,int *type,uint64_t *start,uint64_t *size,int allrecs);
+void cfe_pagetable_init(void);
+
diff --git a/cfe/cfe/include/cfe_timer.h b/cfe/cfe/include/cfe_timer.h
new file mode 100644
index 0000000..8c6a26f
--- /dev/null
+++ b/cfe/cfe/include/cfe_timer.h
@@ -0,0 +1,74 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Timer defs and prototypes File: cfe_timer.h
+ *
+ * Definitions, prototypes, and macros related to the timer.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifndef _CFE_TIMER_T
+#define _CFE_TIMER_T
+
+void cfe_bg_init(void);
+void cfe_bg_add(void (*func)(void *),void *arg);
+void cfe_bg_remove(void (*func)(void *));
+
+void background(void);
+
+#define POLL() background()
+
+typedef int64_t cfe_timer_t;
+
+void cfe_timer_init(void);
+extern volatile int64_t cfe_ticks;
+extern int cfe_cpu_speed;
+
+void cfe_sleep(int ticks);
+void cfe_usleep(int usec);
+
+#define CFE_HZ 10 /* ticks per second */
+
+#define TIMER_SET(x,v) x = cfe_ticks + (v)
+#define TIMER_EXPIRED(x) ((x) && (cfe_ticks > (x)))
+#define TIMER_CLEAR(x) x = 0
+#define TIMER_RUNNING(x) ((x) != 0)
+
+#endif
diff --git a/cfe/cfe/include/cfe_xiocb.h b/cfe/cfe/include/cfe_xiocb.h
new file mode 100644
index 0000000..75a336a
--- /dev/null
+++ b/cfe/cfe/include/cfe_xiocb.h
@@ -0,0 +1,202 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * IOCB definitions File: cfe_iocb.h
+ *
+ * This module describes CFE's IOCB structure, the main
+ * data structure used to communicate API requests with CFE.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifndef _CFE_XIOCB_H
+#define _CFE_XIOCB_H
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define CFE_CMD_FW_GETINFO 0
+#define CFE_CMD_FW_RESTART 1
+#define CFE_CMD_FW_BOOT 2
+#define CFE_CMD_FW_CPUCTL 3
+#define CFE_CMD_FW_GETTIME 4
+#define CFE_CMD_FW_MEMENUM 5
+#define CFE_CMD_FW_FLUSHCACHE 6
+
+#define CFE_CMD_DEV_GETHANDLE 9
+#define CFE_CMD_DEV_ENUM 10
+#define CFE_CMD_DEV_OPEN 11
+#define CFE_CMD_DEV_INPSTAT 12
+#define CFE_CMD_DEV_READ 13
+#define CFE_CMD_DEV_WRITE 14
+#define CFE_CMD_DEV_IOCTL 15
+#define CFE_CMD_DEV_CLOSE 16
+#define CFE_CMD_DEV_GETINFO 17
+
+#define CFE_CMD_ENV_ENUM 20
+#define CFE_CMD_ENV_GET 22
+#define CFE_CMD_ENV_SET 23
+#define CFE_CMD_ENV_DEL 24
+
+#define CFE_CMD_MAX 32
+
+#define CFE_CMD_VENDOR_USE 0x8000 /* codes above this are for customer use */
+
+#define CFE_MI_RESERVED 0 /* memory is reserved, do not use */
+#define CFE_MI_AVAILABLE 1 /* memory is available */
+
+#define CFE_FLG_WARMSTART 0x00000001
+#define CFE_FLG_FULL_ARENA 0x00000001
+#define CFE_FLG_ENV_PERMANENT 0x00000001
+
+#define CFE_CPU_CMD_START 1
+#define CFE_CPU_CMD_STOP 0
+
+#define CFE_STDHANDLE_CONSOLE 0
+
+#define CFE_DEV_NETWORK 1
+#define CFE_DEV_DISK 2
+#define CFE_DEV_FLASH 3
+#define CFE_DEV_SERIAL 4
+#define CFE_DEV_CPU 5
+#define CFE_DEV_NVRAM 6
+#define CFE_DEV_CLOCK 7
+#define CFE_DEV_OTHER 8
+#define CFE_DEV_MASK 0x0F
+
+#define CFE_CACHE_FLUSH_D 1
+#define CFE_CACHE_INVAL_I 2
+#define CFE_CACHE_INVAL_D 4
+#define CFE_CACHE_INVAL_L2 8
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef unsigned long long cfe_xuint_t;
+typedef long long cfe_xint_t;
+typedef long long cfe_xptr_t;
+
+typedef struct xiocb_buffer_s {
+ cfe_xuint_t buf_offset; /* offset on device (bytes) */
+ cfe_xptr_t buf_ptr; /* pointer to a buffer */
+ cfe_xuint_t buf_length; /* length of this buffer */
+ cfe_xuint_t buf_retlen; /* returned length (for read ops) */
+ cfe_xuint_t buf_ioctlcmd; /* IOCTL command (used only for IOCTLs) */
+} xiocb_buffer_t;
+
+#define buf_devflags buf_ioctlcmd /* returned device info flags */
+
+typedef struct xiocb_inpstat_s {
+ cfe_xuint_t inp_status; /* 1 means input available */
+} xiocb_inpstat_t;
+
+typedef struct xiocb_envbuf_s {
+ cfe_xint_t enum_idx; /* 0-based enumeration index */
+ cfe_xptr_t name_ptr; /* name string buffer */
+ cfe_xint_t name_length; /* size of name buffer */
+ cfe_xptr_t val_ptr; /* value string buffer */
+ cfe_xint_t val_length; /* size of value string buffer */
+} xiocb_envbuf_t;
+
+typedef struct xiocb_cpuctl_s {
+ cfe_xuint_t cpu_number; /* cpu number to control */
+ cfe_xuint_t cpu_command; /* command to issue to CPU */
+ cfe_xuint_t start_addr; /* CPU start address */
+ cfe_xuint_t gp_val; /* starting GP value */
+ cfe_xuint_t sp_val; /* starting SP value */
+ cfe_xuint_t a1_val; /* starting A1 value */
+} xiocb_cpuctl_t;
+
+typedef struct xiocb_time_s {
+ cfe_xint_t ticks; /* current time in ticks */
+} xiocb_time_t;
+
+typedef struct xiocb_exitstat_s {
+ cfe_xint_t status;
+} xiocb_exitstat_t;
+
+typedef struct xiocb_meminfo_s {
+ cfe_xint_t mi_idx; /* 0-based enumeration index */
+ cfe_xint_t mi_type; /* type of memory block */
+ cfe_xuint_t mi_addr; /* physical start address */
+ cfe_xuint_t mi_size; /* block size */
+} xiocb_meminfo_t;
+
+#define CFE_FWI_64BIT 0x00000001
+#define CFE_FWI_32BIT 0x00000002
+#define CFE_FWI_RELOC 0x00000004
+#define CFE_FWI_UNCACHED 0x00000008
+#define CFE_FWI_MULTICPU 0x00000010
+#define CFE_FWI_FUNCSIM 0x00000020
+#define CFE_FWI_RTLSIM 0x00000040
+
+typedef struct xiocb_fwinfo_s {
+ cfe_xint_t fwi_version; /* major, minor, eco version */
+ cfe_xint_t fwi_totalmem; /* total installed mem */
+ cfe_xint_t fwi_flags; /* various flags */
+ cfe_xint_t fwi_boardid; /* board ID */
+ cfe_xint_t fwi_bootarea_va; /* VA of boot area */
+ cfe_xint_t fwi_bootarea_pa; /* PA of boot area */
+ cfe_xint_t fwi_bootarea_size; /* size of boot area */
+ cfe_xint_t fwi_reserved1;
+ cfe_xint_t fwi_reserved2;
+ cfe_xint_t fwi_reserved3;
+} xiocb_fwinfo_t;
+
+typedef struct cfe_xiocb_s {
+ cfe_xuint_t xiocb_fcode; /* IOCB function code */
+ cfe_xint_t xiocb_status; /* return status */
+ cfe_xint_t xiocb_handle; /* file/device handle */
+ cfe_xuint_t xiocb_flags; /* flags for this IOCB */
+ cfe_xuint_t xiocb_psize; /* size of parameter list */
+ union {
+ xiocb_buffer_t xiocb_buffer; /* buffer parameters */
+ xiocb_inpstat_t xiocb_inpstat; /* input status parameters */
+ xiocb_envbuf_t xiocb_envbuf; /* environment function parameters */
+ xiocb_cpuctl_t xiocb_cpuctl; /* CPU control parameters */
+ xiocb_time_t xiocb_time; /* timer parameters */
+ xiocb_meminfo_t xiocb_meminfo; /* memory arena info parameters */
+ xiocb_fwinfo_t xiocb_fwinfo; /* firmware information */
+ xiocb_exitstat_t xiocb_exitstat; /* Exit Status */
+ } plist;
+} cfe_xiocb_t;
+
+#endif
diff --git a/cfe/cfe/include/dev_flash.h b/cfe/cfe/include/dev_flash.h
new file mode 100644
index 0000000..8cbce48
--- /dev/null
+++ b/cfe/cfe/include/dev_flash.h
@@ -0,0 +1,168 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Flash memory definitions File: dev_flash.h
+ *
+ * Stuff we use when manipulating flash memory devices.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+/*
+ * AMD Flash commands and magic offsets
+ */
+
+#define AMD_FLASH_MAGIC_ADDR_1 0x555 /* AAA for 16-bit devices in 8-bit mode */
+#define AMD_FLASH_MAGIC_ADDR_2 0x2AA /* 554 for 16-bit devices in 8-bit mode */
+
+#define AMD_FLASH_RESET 0xF0
+#define AMD_FLASH_MAGIC_1 0xAA
+#define AMD_FLASH_MAGIC_2 0x55
+#define AMD_FLASH_AUTOSEL 0x90
+#define AMD_FLASH_PROGRAM 0xA0
+#define AMD_FLASH_UNLOCK_BYPASS 0x20
+#define AMD_FLASH_ERASE_3 0x80
+#define AMD_FLASH_ERASE_4 0xAA
+#define AMD_FLASH_ERASE_5 0x55
+#define AMD_FLASH_ERASE_ALL_6 0x10
+#define AMD_FLASH_ERASE_SEC_6 0x30
+
+/*
+ * INTEL Flash commands and magic offsets
+ */
+
+#define INTEL_FLASH_READ_MODE 0xFF
+#define INTEL_FLASH_ERASE_BLOCK 0x20
+#define INTEL_FLASH_ERASE_CONFIRM 0xD0
+#define INTEL_FLASH_PROGRAM 0x40
+
+/* INTEL Flash commands for 16-bit mode */
+#define INTEL_FLASH_16BIT_READ_MODE 0xFF00
+#define INTEL_FLASH_16BIT_ERASE_BLOCK 0x2000
+#define INTEL_FLASH_16BIT_ERASE_CONFIRM 0xD000
+#define INTEL_FLASH_16BIT_PROGRAM 0x4000
+#define INTEL_FLASH_8BIT 0
+#define INTEL_FLASH_16BIT 1
+
+
+/*
+ * Common Flash Interface (CFI) commands and offsets
+ */
+
+#define FLASH_CFI_QUERY_ADDR 0x55
+#define FLASH_CFI_QUERY_MODE 0x98
+#define FLASH_CFI_QUERY_EXIT 0xFF
+
+#define FLASH_CFI_MANUFACTURER 0x00
+#define FLASH_CFI_DEVICE 0x01
+#define FLASH_CFI_SIGNATURE 0x10
+#define FLASH_CFI_QUERY_STRING 0x10
+#define FLASH_CFI_COMMAND_SET 0x13
+#define FLASH_CFI_DEVICE_SIZE 0x27
+#define FLASH_CFI_DEVICE_INTERFACE 0x28
+#define FLASH_CFI_REGION_COUNT 0x2C
+#define FLASH_CFI_REGION_TABLE 0x2D
+
+#define FLASH_CFI_CMDSET_INTEL_ECS 0x0001 /* Intel extended */
+#define FLASH_CFI_CMDSET_AMD_STD 0x0002 /* AMD Standard */
+#define FLASH_CFI_CMDSET_INTEL_STD 0x0003 /* Intel Standard */
+#define FLASH_CFI_CMDSET_AMD_ECS 0x0004 /* AMD Extended */
+
+#define FLASH_CFI_DEVIF_X8 0x0000 /* 8-bit asynchronous */
+#define FLASH_CFI_DEVIF_X16 0x0001 /* 16-bit asynchronous */
+#define FLASH_CFI_DEVIF_X8X16 0x0002 /* 8 or 16-bit with BYTE# pin */
+#define FLASH_CFI_DEVIF_X32 0x0003 /* 32-bit asynchronous */
+
+/*
+ * JEDEC offsets
+ */
+
+#define FLASH_JEDEC_OFFSET_MFR 0
+#define FLASH_JEDEC_OFFSET_DEV 1
+
+/* Vendor-specific flash identifiers */
+
+#define FLASH_MFR_HYUNDAI 0xAD
+
+/* *********************************************************************
+ * Macros for defining custom sector tables
+ ********************************************************************* */
+
+#define FLASH_SECTOR_RANGE(nblks,size) (((nblks)-1) << 16) + ((size)/256)
+#define FLASH_SECTOR_NBLKS(x) (((x) >> 16)+1)
+#define FLASH_SECTOR_SIZE(x) (((x) & 0xFFFF)*256)
+#define FLASH_MAXSECTORS 8
+
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+/*
+ * This structure is passed in the "probe_ptr" field of the
+ * flash's probe routines and can be used for advanced
+ * configuration. If you pass this structure, probe_a and
+ * probe_b will be ignored by the driver
+ *
+ * flash_prog_phys is the base address you use for flash commands -
+ * you can put 0 here if it's the same as flash_phys. some boards,
+ * like the Algor P5064, have a different PA region used for doing
+ * byte accesses to the flash. In this case the special
+ * "flash_prog_phys" field is used for that.
+ */
+
+
+#define FLASH_FLG_NVRAM 0x00000001 /* Reserve space for NVRAM */
+#define FLASH_FLG_AUTOSIZE 0x00000002 /* resize to actual device size */
+#define FLASH_FLG_16BIT 0x00000004 /* it's a 16-bit ROM in 16-bit mode */
+#define FLASH_FLG_MANUAL 0x00000008 /* Not CFI, manual sectoring */
+#define FLASH_FLG_WIDE 0x00000010 /* must shift control addresses left one bit */
+
+#ifndef __ASSEMBLER__
+typedef struct flash_probe_t {
+ long flash_phys;
+ long flash_prog_phys; /* base address for programming, if different */
+ int flash_size; /* total flash size */
+ int flash_flags;
+ /* The following are used when manually sectoring */
+ int flash_cmdset;
+ int flash_nsectors; /* number of ranges */
+ int flash_sectors[FLASH_MAXSECTORS];
+} flash_probe_t;
+#endif
diff --git a/cfe/cfe/include/dev_ide.h b/cfe/cfe/include/dev_ide.h
new file mode 100644
index 0000000..96d3e18
--- /dev/null
+++ b/cfe/cfe/include/dev_ide.h
@@ -0,0 +1,90 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * IDE disk driver File: dev_ide.h
+ *
+ * Probe constants for the IDE disk device. Various flags
+ * can be passed to the probe routine to configure various
+ * things. This is where they are defined.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+/*
+ * Use the macros below to set the type of the master and slave devices
+ * on the IDE bus. If you want automatic probing, then you need
+ * to specify that IDE_DEV_TYPE_AUTO as the device type.
+ */
+
+
+/*
+ * XXX: If you have more than one PCI IDE controller
+ * installed, this will be applied to all installed
+ * controllers. Clearly not right, we'll need to add
+ * a field here for a controller index.
+ */
+
+
+#define IDE_PROBE_TYPE_MASK 0x0F
+#define IDE_PROBE_MASTER_SHIFT 0
+#define IDE_PROBE_SLAVE_SHIFT 4
+
+#define IDE_PROBE_MASTER_TYPE(x) ((x) << IDE_PROBE_MASTER_SHIFT)
+#define IDE_PROBE_SLAVE_TYPE(x) ((x) << IDE_PROBE_SLAVE_SHIFT)
+
+#define IDE_PROBE_GET_TYPE(pb,unit) (((pb) >> (unit*4)) & IDE_PROBE_TYPE_MASK)
+
+/*
+ * Device types.
+ */
+
+#define IDE_DEVTYPE_NOPROBE 0 /* none */
+#define IDE_DEVTYPE_AUTO 0x0F /* automatically probe */
+
+#define IDE_DEVTYPE_DISK 1 /* hard drives */
+#define IDE_DEVTYPE_CDROM 2 /* CD-ROMs */
+#define IDE_DEVTYPE_ATAPIDISK 3 /* ZIP disks, etc. */
+
+
+
diff --git a/cfe/cfe/include/dev_ide_common.h b/cfe/cfe/include/dev_ide_common.h
new file mode 100644
index 0000000..736fd99
--- /dev/null
+++ b/cfe/cfe/include/dev_ide_common.h
@@ -0,0 +1,204 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Generic IDE disk driver File: dev_ide_common.c
+ *
+ * This file contains common constants and structures for IDE
+ * disks and CFE drivers for them.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define IDE_REG_DATA 0x0
+#define IDE_REG_ERROR 0x1
+#define IDE_REG_PRECOMP 0x1
+#define IDE_REG_SECCNT 0x2
+#define IDE_REG_IR 0x2 /* ATAPI */
+#define IDE_REG_SECNUM 0x3
+#define IDE_REG_BCLSB 0x4 /* ATAPI */
+#define IDE_REG_BCMSB 0x5 /* ATAPI */
+#define IDE_REG_CYLLSB 0x4
+#define IDE_REG_CYLMSB 0x5
+#define IDE_REG_DRVHD 0x6
+#define IDE_REG_STATUS 0x7
+#define IDE_REG_COMMAND 0x7
+#define IDE_REG_ALTSTAT 0x6 /* Note: ALTSTAT is really 0x3F6, what do we do? */
+#define IDE_REG_DIGOUT 0x6
+
+#define IDE_IR_CD 0x01 /* 1 = command, 0 = data */
+#define IDE_IR_IO 0x02 /* 1 = from device, 0 = to device */
+#define IDE_IR_REL 0x04
+
+#define IDE_ERR_BBK 0x80 /* sector marked bad by host */
+#define IDE_ERR_UNC 0x40 /* uncorrectable error */
+#define IDE_ERR_MC 0x20 /* medium changed */
+#define IDE_ERR_NID 0x10 /* no ID mark found */
+#define IDE_ERR_MCR 0x08 /* medium change required */
+#define IDE_ERR_ABT 0x04 /* command aborted */
+#define IDE_ERR_NT0 0x02 /* track 0 not found */
+#define IDE_ERR_NDM 0x01 /* address mark not found */
+
+#define IDE_DRV_SLAVE 0x10
+#define IDE_DRV_LBA 0x40
+#define IDE_DRV_MBO 0xA0
+#define IDE_DRV_HDMASK 0x0F
+
+#define IDE_STS_BSY 0x80 /* drive is busy */
+#define IDE_STS_RDY 0x40 /* drive is ready */
+#define IDE_STS_WFT 0x20 /* write fault */
+#define IDE_STS_SKC 0x10 /* seek complete */
+#define IDE_STS_DRQ 0x08 /* data can be transferred */
+#define IDE_STS_CORR 0x04 /* correctable data error */
+#define IDE_STS_IDX 0x02 /* index mark just passed */
+#define IDE_STS_ERR 0x01 /* Error register contains info */
+
+#define IDE_CMD_RECAL 0x10
+#define IDE_CMD_READ 0x20
+#define IDE_CMD_READRETRY 0x21
+#define IDE_CMD_WRITE 0x30
+#define IDE_CMD_READVERIFY 0x40
+#define IDE_CMD_DIAGNOSTIC 0x90
+#define IDE_CMD_INITPARAMS 0x91
+#define IDE_CMD_SETMULTIPLE 0xC6
+#define IDE_CMD_POWER_MODE 0xE5
+#define IDE_CMD_DRIVE_INFO 0xEC
+
+#define IDE_CMD_ATAPI_SOFTRESET 0x08
+#define IDE_CMD_ATAPI_PACKET 0xA0
+#define IDE_CMD_ATAPI_IDENTIFY 0xA1
+#define IDE_CMD_ATAPI_SERVICE 0xA2
+
+#define IDE_DOR_SRST 0x04
+#define IDE_DOR_IEN 0x02
+
+#define DISK_SECTORSIZE 512
+#define CDROM_SECTORSIZE 2048
+#define MAX_SECTORSIZE 2048
+
+#define ATAPI_SENSE_MASK 0xF0
+#define ATAPI_SENSE_NONE 0x00
+#define ATAPI_SENSE_RECOVERED 0x10
+#define ATAPI_SENSE_NOTREADY 0x20
+#define ATAPI_SENSE_MEDIUMERROR 0x30
+#define ATAPI_SENSE_HWERROR 0x40
+#define ATAPI_SENSE_ILLREQUEST 0x50
+#define ATAPI_SENSE_ATTENTION 0x60
+#define ATAPI_SENSE_PROTECT 0x70
+#define ATAPI_SENSE_BLANKCHECK 0x80
+#define ATAPI_SENSE_VSPECIFIC 0x90
+#define ATAPI_SENSE_COPYABORT 0xA0
+#define ATAPI_SENSE_CMDABORT 0xB0
+#define ATAPI_SENSE_EQUAL 0xC0
+#define ATAPI_SENSE_VOLOVERFLOW 0xD0
+#define ATAPI_SENSE_MISCOMPARE 0xE0
+#define ATAPI_SENSE_RESERVED 0xF0
+
+#define ATAPI_SIG_LSB 0x14
+#define ATAPI_SIG_MSB 0xEB
+
+#define CDB_CMD_READ 0x28
+#define CDB_CMD_WRITE 0x2A
+#define CDB_CMD_REQSENSE 0x03
+
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef struct idecommon_dispatch_s idecommon_dispatch_t;
+
+struct idecommon_dispatch_s {
+ void *ref;
+ uint32_t baseaddr;
+ uint8_t (*inb)(idecommon_dispatch_t *disp,uint32_t reg);
+ uint16_t (*inw)(idecommon_dispatch_t *disp,uint32_t reg);
+ void (*ins)(idecommon_dispatch_t *disp,uint32_t reg,uint8_t *buf,int len);
+
+ void (*outb)(idecommon_dispatch_t *disp,uint32_t reg,uint8_t val);
+ void (*outw)(idecommon_dispatch_t *disp,uint32_t reg,uint16_t val);
+ void (*outs)(idecommon_dispatch_t *disp,uint32_t reg,uint8_t *buf,int len);
+};
+
+#define IDEDISP_WRITEREG8(ide,reg,val) (*((ide)->outb))(ide,reg,val)
+#define IDEDISP_WRITEREG16(ide,reg,val) (*((ide)->outw))(ide,reg,val)
+#define IDEDISP_WRITEBUF(ide,reg,buf,len) (*((ide)->outs))(ide,reg,buf,len)
+#define IDEDISP_READREG8(ide,reg) (*((ide)->inb))(ide,reg)
+#define IDEDISP_READREG16(ide,reg) (*((ide)->inw))(ide,reg)
+#define IDEDISP_READBUF(ide,reg,buf,len) (*((ide)->ins))(ide,reg,buf,len)
+
+typedef struct idecommon_s idecommon_t;
+
+struct idecommon_s {
+ idecommon_dispatch_t *idecommon_dispatch;
+ unsigned long idecommon_addr; /* physical address */
+ int idecommon_unit; /* 0 or 1 master/slave */
+ int idecommon_sectorsize; /* size of each sector */
+ long long idecommon_ttlsect; /* total sectors */
+ int idecommon_atapi; /* 1 if ATAPI device */
+ int idecommon_devtype; /* device type */
+ uint64_t idecommon_deferprobe; /* Defer probe to open */
+ uint32_t idecommon_flags; /* flags for underlying driver */
+ int (*idecommon_readfunc)(idecommon_t *ide,uint64_t lba,int numsec,uint8_t *buffer);
+ int (*idecommon_writefunc)(idecommon_t *ide,uint64_t lba,int numsec,uint8_t *buffer);
+
+ uint32_t timer;
+};
+
+
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+extern void idecommon_init(idecommon_t *ide,int devtype);
+extern int idecommon_open(cfe_devctx_t *ctx);
+extern int idecommon_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+extern int idecommon_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+extern int idecommon_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+extern int idecommon_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+extern int idecommon_identify(idecommon_t *ide,unsigned char *buffer);
+extern int idecommon_close(cfe_devctx_t *ctx);
+extern int idecommon_devprobe(idecommon_t *ide,int noisy);
+void idecommon_attach(cfe_devdisp_t *disp);
+
diff --git a/cfe/cfe/include/dev_newflash.h b/cfe/cfe/include/dev_newflash.h
new file mode 100644
index 0000000..5efced0
--- /dev/null
+++ b/cfe/cfe/include/dev_newflash.h
@@ -0,0 +1,344 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Flash memory definitions File: dev_newflash.h
+ *
+ * Stuff we use when manipulating flash memory devices.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifndef __ASSEMBLER__
+#include "cfe_device.h"
+#include "cfe_iocb.h"
+#endif
+
+/* *********************************************************************
+ * Configuration
+ ********************************************************************* */
+
+/* Bits for compile-time removal of features */
+#define FLASH_DRIVER_INTEL 1 /* support Intel cmd sets */
+#define FLASH_DRIVER_AMD 2 /* support AMD cmd sets */
+#define FLASH_DRIVER_CFI 4 /* support auto probing */
+
+/* Default value unless overridden in bsp_config.h */
+#ifndef FLASH_DRIVERS
+#define FLASH_DRIVERS (FLASH_DRIVER_INTEL | FLASH_DRIVER_AMD | FLASH_DRIVER_CFI)
+#endif
+
+/* *********************************************************************
+ * Flash magic numbers
+ ********************************************************************* */
+
+/*
+ * AMD Flash commands and magic offsets
+ */
+
+#define AMD_FLASH_MAGIC_ADDR_1 0x555 /* AAA for 16-bit devices in 8-bit mode */
+#define AMD_FLASH_MAGIC_ADDR_2 0x2AA /* 554 for 16-bit devices in 8-bit mode */
+
+#define AMD_FLASH_RESET 0xF0
+#define AMD_FLASH_MAGIC_1 0xAA
+#define AMD_FLASH_MAGIC_2 0x55
+#define AMD_FLASH_AUTOSEL 0x90
+#define AMD_FLASH_DEVCODE8 0x2
+#define AMD_FLASH_DEVCODE16 0x1
+#define AMD_FLASH_DEVCODE16B 0x2
+#define AMD_FLASH_MANID 0x0
+#define AMD_FLASH_PROGRAM 0xA0
+#define AMD_FLASH_UNLOCK_BYPASS 0x20
+#define AMD_FLASH_ERASE_3 0x80
+#define AMD_FLASH_ERASE_4 0xAA
+#define AMD_FLASH_ERASE_5 0x55
+#define AMD_FLASH_ERASE_ALL_6 0x10
+#define AMD_FLASH_ERASE_SEC_6 0x30
+
+/*
+ * INTEL Flash commands and magic offsets
+ */
+
+#define INTEL_FLASH_READ_MODE 0xFF
+#define INTEL_FLASH_ERASE_BLOCK 0x20
+#define INTEL_FLASH_ERASE_CONFIRM 0xD0
+#define INTEL_FLASH_PROGRAM 0x40
+
+/* INTEL Flash commands for 16-bit mode */
+#define INTEL_FLASH_16BIT_READ_MODE 0xFF00
+#define INTEL_FLASH_16BIT_ERASE_BLOCK 0x2000
+#define INTEL_FLASH_16BIT_ERASE_CONFIRM 0xD000
+#define INTEL_FLASH_16BIT_PROGRAM 0x4000
+#define INTEL_FLASH_8BIT 0
+#define INTEL_FLASH_16BIT 1
+
+
+/*
+ * Common Flash Interface (CFI) commands and offsets
+ */
+
+#define FLASH_CFI_QUERY_ADDR 0x55
+#define FLASH_CFI_QUERY_MODE 0x98
+#define FLASH_CFI_QUERY_EXIT 0xFF
+
+#define FLASH_CFI_MANUFACTURER 0x00
+#define FLASH_CFI_DEVICE 0x01
+#define FLASH_CFI_SIGNATURE 0x10
+#define FLASH_CFI_QUERY_STRING 0x10
+#define FLASH_CFI_COMMAND_SET 0x13
+#define FLASH_CFI_DEVICE_SIZE 0x27
+#define FLASH_CFI_DEVICE_INTERFACE 0x28
+#define FLASH_CFI_REGION_COUNT 0x2C
+#define FLASH_CFI_REGION_TABLE 0x2D
+
+#define FLASH_CFI_CMDSET_INTEL_ECS 0x0001 /* Intel extended */
+#define FLASH_CFI_CMDSET_AMD_STD 0x0002 /* AMD Standard */
+#define FLASH_CFI_CMDSET_INTEL_STD 0x0003 /* Intel Standard */
+#define FLASH_CFI_CMDSET_AMD_ECS 0x0004 /* AMD Extended */
+
+#define FLASH_CFI_DEVIF_X8 0x0000 /* 8-bit asynchronous */
+#define FLASH_CFI_DEVIF_X16 0x0001 /* 16-bit asynchronous */
+#define FLASH_CFI_DEVIF_X8X16 0x0002 /* 8 or 16-bit with BYTE# pin */
+#define FLASH_CFI_DEVIF_X32 0x0003 /* 32-bit asynchronous */
+
+/*
+ * JEDEC offsets
+ */
+
+#define FLASH_JEDEC_OFFSET_MFR 0
+#define FLASH_JEDEC_OFFSET_DEV 1
+
+/* Vendor-specific flash identifiers */
+
+#define FLASH_MFR_HYUNDAI 0xAD
+#define FLASH_MFR_AMD 0x01
+
+/* *********************************************************************
+ * Macros for defining custom sector tables
+ ********************************************************************* */
+
+#define FLASH_SECTOR_RANGE(nblks,size) (((nblks)-1) << 16) + ((size)/256)
+#define FLASH_SECTOR_NBLKS(x) (((x) >> 16)+1)
+#define FLASH_SECTOR_SIZE(x) (((x) & 0xFFFF)*256)
+#define FLASH_MAXSECTORS 8
+
+/* *********************************************************************
+ * Flashop engine constants and structures
+ * The flashop engine interprets a little table of commands
+ * to manipulate flash parts - we do this so we can operate
+ * on the flash that we're currently running from.
+ ********************************************************************* */
+
+/*
+ * Structure of the "instruction" table is six words,
+ * size dependant on the machine word size (32 or 64 bits).
+ *
+ * opcode
+ * flash base
+ * destination
+ * source
+ * length
+ * result
+ */
+
+#define FEINST_OP _TBLIDX(0)
+#define FEINST_BASE _TBLIDX(1)
+#define FEINST_DEST _TBLIDX(2)
+#define FEINST_SRC _TBLIDX(3)
+#define FEINST_CNT _TBLIDX(4)
+#define FEINST_RESULT _TBLIDX(5)
+#define FEINST_SIZE _TBLIDX(6) /* size of an instruction */
+
+#ifndef __ASSEMBLER__
+typedef struct flashinstr_s { /* must match offsets above */
+ long fi_op;
+ long fi_base;
+ long fi_dest;
+ long fi_src;
+ long fi_cnt;
+ long fi_result;
+} flashinstr_t;
+#endif
+
+/*
+ * Flash opcodes
+ */
+
+#define FEOP_RETURN 0 /* return to CFE */
+#define FEOP_REBOOT 1 /* Reboot system */
+#define FEOP_READ8 2 /* read, 8 bits at a time */
+#define FEOP_READ16 3 /* read, 16 bits at a time */
+#define FEOP_CFIQUERY8 4 /* CFI Query 8-bit */
+#define FEOP_CFIQUERY16 5 /* CFI Query 16-bit */
+#define FEOP_CFIQUERY16B 6 /* CFI Query 16-bit */
+#define FEOP_MEMCPY 7 /* generic memcpy */
+#define FEOP_AMD_ERASE8 8 /* AMD-style 8-bit erase-sector */
+#define FEOP_AMD_ERASE16 9 /* AMD-style 16-bit erase-sector */
+#define FEOP_AMD_ERASE16B 10 /* AMD-style 16-bit erase-sector */
+#define FEOP_AMD_PGM8 11 /* AMD-style 8-bit program */
+#define FEOP_AMD_PGM16 12 /* AMD-style 16-bit program */
+#define FEOP_AMD_PGM16B 13 /* AMD-style 16-bit program */
+#define FEOP_AMD_DEVCODE8 14 /* AMD-style 8-bit Boot Block Info */
+#define FEOP_AMD_DEVCODE16 15 /* AMD-style 8-bit Boot Block Info */
+#define FEOP_AMD_DEVCODE16B 16 /* AMD-style 8-bit Boot Block Info */
+#define FEOP_AMD_MANID8 17 /* AMD-style 8-bit Boot Block Info */
+#define FEOP_AMD_MANID16 18 /* AMD-style 8-bit Boot Block Info */
+#define FEOP_AMD_MANID16B 19 /* AMD-style 8-bit Boot Block Info */
+#define FEOP_INTEL_ERASE8 20 /* Intel-style 8-bit erase-sector */
+#define FEOP_INTEL_ERASE16 21 /* Intel-style 16-bit erase-sector */
+#define FEOP_INTEL_PGM8 22 /* Intel-style 8-bit program */
+#define FEOP_INTEL_PGM16 23 /* Intel-style 16-bit program */
+
+/*
+ * Flashop result values.
+ */
+
+#define FERES_OK 0
+#define FERES_ERROR -1
+
+
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+/*
+ * Flags. If you instantiate the driver with probe_a = physical
+ * address and probe_b = size, you should also OR in the
+ * bus and device width below.
+ */
+
+#define FLASH_FLG_AUTOSIZE 0x00000002 /* resize to actual device size */
+#define FLASH_FLG_BUS8 0
+#define FLASH_FLG_BUS16 0x00000004 /* ROM is connected to 16-bit bus */
+#define FLASH_FLG_DEV8 0
+#define FLASH_FLG_DEV16 0x00000010 /* ROM has 16-bit data width */
+#define FLASH_FLG_MANUAL 0x00000008 /* Not CFI, manual sectoring */
+#define FLASH_FLG_MASK 0x000000FF /* mask of probe bits for flags */
+#define FLASH_SIZE_MASK 0xFFFFFF00 /* mask of probe bits for size */
+/* you don't have to shift the size, we assume it's in multiples of 256bytes */
+
+#ifndef __ASSEMBLER__
+
+/*
+ * Partition structure - use this to define a flash "partition."
+ * The partitions are assigned in order from the beginning of the flash.
+ * The special size '0' means 'fill to end of flash', and you can
+ * have more partitions after that which are aligned with the top
+ * of the flash.
+ * Therefore if you have a 1MB flash and set up
+ * partitions for 256KB, 0, 128KB, the 128KB part will be aligned
+ * to the top of the flash and the middle block will be 768KB.
+ * Partitions can be on byte boundaries.
+ */
+
+typedef struct newflash_part_t {
+ int fp_size;
+ char *fp_name;
+} newflash_part_t;
+#define FLASH_MAX_PARTITIONS 8
+
+/*
+ * Probe structure - this is used when we want to describe to the flash
+ * driver the layout of our flash, particularly when you want to
+ * manually describe the sectors.
+ */
+
+typedef struct newflash_probe_t {
+ long flash_phys; /* physical address of flash */
+ int flash_size; /* total flash size */
+ int flash_flags; /* flags (FLASH_FLG_xxx) */
+ int flash_type; /* FLASH_TYPE_xxx */
+ /* The following are used when manually sectoring */
+ int flash_cmdset; /* FLASH_CMDSET_xxx */
+ int flash_nsectors; /* number of ranges */
+ int flash_sectors[FLASH_MAXSECTORS];
+ /* This says how many contiguous flash chips are in this region */
+ int flash_nchips; /* "flash_size" is just for one chip */
+ /* The following are used for partitioned flashes */
+ int flash_nparts; /* zero means not partitioned */
+ newflash_part_t flash_parts[FLASH_MAX_PARTITIONS];
+ /* The following are used for whacky, weird flashes */
+ int (*flash_ioctl_hook)(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+ /* You can replace the flash engine with your own */
+ int (*flash_engine_hook)(flashinstr_t *prog);
+} newflash_probe_t;
+
+
+/* *********************************************************************
+ * PRIVATE STRUCTURES
+ *
+ * These structures are actually the "property" of the
+ * flash driver. The only reason a board package might
+ * want to dig around in here is if it implements a hook
+ * or overrides functions to support special, weird flash parts.
+ ********************************************************************* */
+
+typedef struct flashdev_s flashdev_t;
+
+typedef struct flashpart_s {
+ flashdev_t *fp_dev;
+ int fp_offset;
+ int fp_size;
+} flashpart_t;
+
+#define FLASH_MAX_CFIDATA 256 /* total size of CFI Data */
+#define FLASH_MAX_INST 8 /* instructions we use during probing */
+
+struct flashdev_s {
+ newflash_probe_t fd_probe; /* probe information */
+
+ uint8_t fd_erasefunc; /* Erase routine to use */
+ uint8_t fd_pgmfunc; /* program routine to use */
+ uint8_t fd_readfunc; /* Read routine to use */
+ flashpart_t fd_parts[FLASH_MAX_PARTITIONS];
+
+ uint8_t *fd_sectorbuffer; /* sector copy buffer */
+ int fd_ttlsect; /* total sectors on one device */
+ int fd_ttlsize; /* total size of all devices (flash size * nchips) */
+
+ int fd_iptr; /* flashop engine instructions */
+ flashinstr_t *fd_inst;
+};
+
+
+
+#endif
+
+
+
diff --git a/cfe/cfe/include/elf.h b/cfe/cfe/include/elf.h
new file mode 100644
index 0000000..944aab4
--- /dev/null
+++ b/cfe/cfe/include/elf.h
@@ -0,0 +1,194 @@
+/*
+ * ELF data structures and values
+ */
+
+typedef unsigned short Elf32_Half;
+typedef unsigned int Elf32_Word;
+typedef signed int Elf32_Sword;
+typedef unsigned int Elf32_Off;
+typedef unsigned int Elf32_Addr;
+typedef unsigned char Elf_Char;
+
+/*
+ * File Header
+ */
+
+#define EI_NIDENT 16
+
+typedef struct {
+ Elf_Char e_ident[EI_NIDENT];
+ Elf32_Half e_type;
+ Elf32_Half e_machine;
+ Elf32_Word e_version;
+ Elf32_Addr e_entry;
+ Elf32_Off e_phoff;
+ Elf32_Off e_shoff;
+ Elf32_Word e_flags;
+ Elf32_Half e_ehsize;
+ Elf32_Half e_phentsize;
+ Elf32_Half e_phnum;
+ Elf32_Half e_shentsize;
+ Elf32_Half e_shnum;
+ Elf32_Half e_shstrndx;
+} Elf32_Ehdr;
+
+/* e_indent */
+#define EI_MAG0 0 /* File identification byte 0 index */
+#define EI_MAG1 1 /* File identification byte 1 index */
+#define EI_MAG2 2 /* File identification byte 2 index */
+#define EI_MAG3 3 /* File identification byte 3 index */
+#define EI_CLASS 4 /* File class */
+#define ELFCLASSNONE 0 /* Invalid class */
+#define ELFCLASS32 1 /* 32-bit objects */
+#define ELFCLASS64 2 /* 64-bit objects */
+#define EI_DATA 5 /* Data encoding */
+#define ELFDATANONE 0 /* Invalid data encoding */
+#define ELFDATA2LSB 1 /* 2's complement, little endian */
+#define ELFDATA2MSB 2 /* 2's complement, big endian */
+#define EI_VERSION 6 /* File version */
+#define EI_PAD 7 /* Start of padding bytes */
+
+#define ELFMAG0 0x7F /* Magic number byte 0 */
+#define ELFMAG1 'E' /* Magic number byte 1 */
+#define ELFMAG2 'L' /* Magic number byte 2 */
+#define ELFMAG3 'F' /* Magic number byte 3 */
+
+/* e_type */
+#define ET_NONE 0 /* No file type */
+#define ET_REL 1 /* Relocatable file */
+#define ET_EXEC 2 /* Executable file */
+#define ET_DYN 3 /* Shared object file */
+#define ET_CORE 4 /* Core file */
+#define ET_LOPROC 0xFF00 /* Processor-specific */
+#define ET_HIPROC 0xFFFF /* Processor-specific */
+
+/* e_machine */
+#define EM_NONE 0 /* No machine */
+#define EM_M32 1 /* AT&T WE 32100 */
+#define EM_SPARC 2 /* SUN SPARC */
+#define EM_386 3 /* Intel 80386 */
+#define EM_68K 4 /* Motorola m68k family */
+#define EM_88K 5 /* Motorola m88k family */
+#define EM_860 7 /* Intel 80860 */
+#define EM_MIPS 8 /* MIPS R3000 */
+
+/* e_version */
+#define EV_NONE 0 /* Invalid ELF version */
+#define EV_CURRENT 1 /* Current version */
+
+
+/*
+ * Program Header
+ */
+typedef struct {
+ Elf32_Word p_type; /* Identifies program segment type */
+ Elf32_Off p_offset; /* Segment file offset */
+ Elf32_Addr p_vaddr; /* Segment virtual address */
+ Elf32_Addr p_paddr; /* Segment physical address */
+ Elf32_Word p_filesz; /* Segment size in file */
+ Elf32_Word p_memsz; /* Segment size in memory */
+ Elf32_Word p_flags; /* Segment flags */
+ Elf32_Word p_align; /* Segment alignment, file & memory */
+} Elf32_Phdr;
+
+
+/* p_type */
+#define PT_NULL 0 /* Program header table entry unused */
+#define PT_LOAD 1 /* Loadable program segment */
+#define PT_DYNAMIC 2 /* Dynamic linking information */
+#define PT_INTERP 3 /* Program interpreter */
+#define PT_NOTE 4 /* Auxiliary information */
+#define PT_SHLIB 5 /* Reserved, unspecified semantics */
+#define PT_PHDR 6 /* Entry for header table itself */
+#define PT_LOPROC 0x70000000 /* Processor-specific */
+#define PT_HIPROC 0x7FFFFFFF /* Processor-specific */
+
+/* p_flags */
+#define PF_X (1 << 0) /* Segment is executable */
+#define PF_W (1 << 1) /* Segment is writable */
+#define PF_R (1 << 2) /* Segment is readable */
+#define PF_MASKPROC 0xF0000000 /* Processor-specific reserved bits */
+
+
+/*
+ * Section Header
+ */
+typedef struct {
+ Elf32_Word sh_name;
+ Elf32_Word sh_type;
+ Elf32_Word sh_flags;
+ Elf32_Addr sh_addr;
+ Elf32_Off sh_offset;
+ Elf32_Word sh_size;
+ Elf32_Word sh_link;
+ Elf32_Word sh_info;
+ Elf32_Word sh_addralign;
+ Elf32_Word sh_entsize;
+} Elf32_Shdr;
+
+/* sh_type */
+#define SHT_NULL 0 /* Section header table entry unused */
+#define SHT_PROGBITS 1 /* Program specific (private) data */
+#define SHT_SYMTAB 2 /* Link editing symbol table */
+#define SHT_STRTAB 3 /* A string table */
+#define SHT_RELA 4 /* Relocation entries with addends */
+#define SHT_HASH 5 /* A symbol hash table */
+#define SHT_DYNAMIC 6 /* Information for dynamic linking */
+#define SHT_NOTE 7 /* Information that marks file */
+#define SHT_NOBITS 8 /* Section occupies no space in file */
+#define SHT_REL 9 /* Relocation entries, no addends */
+#define SHT_SHLIB 10 /* Reserved, unspecified semantics */
+#define SHT_DYNSYM 11 /* Dynamic linking symbol table */
+#define SHT_LOPROC 0x70000000 /* Processor-specific semantics, lo */
+#define SHT_HIPROC 0x7FFFFFFF /* Processor-specific semantics, hi */
+#define SHT_LOUSER 0x80000000 /* Application-specific semantics */
+#define SHT_HIUSER 0x8FFFFFFF /* Application-specific semantics */
+
+/* sh_flags */
+#define SHF_WRITE (1 << 0) /* Writable data during execution */
+#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
+#define SHF_EXECINSTR (1 << 2) /* Executable machine instructions */
+#define SHF_MASKPROC 0xF0000000 /* Processor-specific semantics */
+
+
+/*
+ * Symbol Table
+ */
+typedef struct {
+ Elf32_Word st_name;
+ Elf32_Addr st_value;
+ Elf32_Word st_size;
+ Elf_Char st_info;
+ Elf_Char st_other;
+ Elf32_Half st_shndx;
+} Elf32_Sym;
+
+
+#define ELF_ST_BIND(val) (((unsigned int)(val)) >> 4)
+#define ELF_ST_TYPE(val) ((val) & 0xF)
+#define ELF_ST_INFO(bind,type) (((bind) << 4) | ((type) & 0xF))
+
+/* symbol binding */
+#define STB_LOCAL 0 /* Symbol not visible outside obj */
+#define STB_GLOBAL 1 /* Symbol visible outside obj */
+#define STB_WEAK 2 /* Like globals, lower precedence */
+#define STB_LOPROC 13 /* Application-specific semantics */
+#define STB_HIPROC 15 /* Application-specific semantics */
+
+/* symbol type */
+#define STT_NOTYPE 0 /* Symbol type is unspecified */
+#define STT_OBJECT 1 /* Symbol is a data object */
+#define STT_FUNC 2 /* Symbol is a code object */
+#define STT_SECTION 3 /* Symbol associated with a section */
+#define STT_FILE 4 /* Symbol gives a file name */
+#define STT_LOPROC 13 /* Application-specific semantics */
+#define STT_HIPROC 15 /* Application-specific semantics */
+
+/* special values st_shndx */
+#define SHN_UNDEF 0 /* Undefined section reference */
+#define SHN_LORESERV 0xFF00 /* Begin range of reserved indices */
+#define SHN_LOPROC 0xFF00 /* Begin range of appl-specific */
+#define SHN_HIPROC 0xFF1F /* End range of appl-specific */
+#define SHN_ABS 0xFFF1 /* Associated symbol is absolute */
+#define SHN_COMMON 0xFFF2 /* Associated symbol is in common */
+#define SHN_HIRESERVE 0xFFFF /* End range of reserved indices */
diff --git a/cfe/cfe/include/env_subr.h b/cfe/cfe/include/env_subr.h
new file mode 100644
index 0000000..f5dfb9f
--- /dev/null
+++ b/cfe/cfe/include/env_subr.h
@@ -0,0 +1,117 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Environment helper routines File: env_subr.h
+ *
+ * Definitions and prototypes for environment variable subroutines
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+
+/*
+ * TLV types. These codes are used in the "type-length-value"
+ * encoding of the items stored in the NVRAM device (flash or EEPROM)
+ *
+ * The layout of the flash/nvram is as follows:
+ *
+ * <type> <length> <data ...> <type> <length> <data ...> <type_end>
+ *
+ * The type code of "ENV_TLV_TYPE_END" marks the end of the list.
+ * The "length" field marks the length of the data section, not
+ * including the type and length fields.
+ *
+ * Environment variables are stored as follows:
+ *
+ * <type_env> <length> <flags> <name> = <value>
+ *
+ * If bit 0 (low bit) is set, the length is an 8-bit value.
+ * If bit 0 (low bit) is clear, the length is a 16-bit value
+ *
+ * Bit 7 set indicates "user" TLVs. In this case, bit 0 still
+ * indicates the size of the length field.
+ *
+ * Flags are from the constants below:
+ *
+ */
+
+#define ENV_LENGTH_16BITS 0x00 /* for low bit */
+#define ENV_LENGTH_8BITS 0x01
+
+#define ENV_TYPE_USER 0x80
+
+#define ENV_CODE_SYS(n,l) (((n)<<1)|(l))
+#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER)
+
+/*
+ * The actual TLV types we support
+ */
+
+#define ENV_TLV_TYPE_END 0x00
+#define ENV_TLV_TYPE_ENV ENV_CODE_SYS(0,ENV_LENGTH_8BITS)
+
+/*
+ * Environment variable flags
+ */
+
+#define ENV_FLG_NORMAL 0x00 /* normal read/write */
+#define ENV_FLG_BUILTIN 0x01 /* builtin - not stored in flash */
+#define ENV_FLG_READONLY 0x02 /* read-only - cannot be changed */
+
+#define ENV_FLG_MASK 0xFF /* mask of attributes we keep */
+#define ENV_FLG_ADMIN 0x100 /* lets us internally override permissions */
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+int env_delenv(const char *name);
+char *env_getenv(const char *name);
+int env_setenv(const char *name,char *value,int flags);
+int env_load(void);
+int env_save(void);
+int env_enum(int idx,char *name,int *namelen,char *val,int *vallen);
+int env_envtype(const char *name);
+
diff --git a/cfe/cfe/include/foxconnCfg.h b/cfe/cfe/include/foxconnCfg.h
new file mode 100755
index 0000000..3c43675
--- /dev/null
+++ b/cfe/cfe/include/foxconnCfg.h
@@ -0,0 +1,9 @@
+#ifndef _FOXCONNCFG_H
+#define _FOXCONNCFG_H
+
+#define FOXCONN_BOARD_ID "U12L161T00_NETGEAR"
+#define GPIO_POWER_RED_LED 18
+#define GPIO_POWER_RED_LED_ON 1
+#define GPIO_POWER_RED_LED_OFF 0
+
+#endif \ No newline at end of file
diff --git a/cfe/cfe/include/lib_arena.h b/cfe/cfe/include/lib_arena.h
new file mode 100644
index 0000000..2ae49d6
--- /dev/null
+++ b/cfe/cfe/include/lib_arena.h
@@ -0,0 +1,76 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Arena definitions File: lib_arena.h
+ *
+ * Definitions for the arena manager, which is used to keep
+ * track of ranges of physical memory.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef struct arena_node_s {
+ queue_t an_next;
+ uint64_t an_address;
+ uint64_t an_length;
+ int an_type;
+ char *an_descr;
+} arena_node_t;
+
+
+typedef struct arena_s {
+ queue_t arena_list;
+ uint64_t arena_base;
+ uint64_t arena_size;
+} arena_t;
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+int arena_markrange(arena_t *arena,uint64_t address,uint64_t length,
+ int type,char *descr);
+void arena_init(arena_t *arena,uint64_t physmembase,uint64_t physmemsize);
+
diff --git a/cfe/cfe/include/lib_malloc.h b/cfe/cfe/include/lib_malloc.h
new file mode 100644
index 0000000..da1e27b
--- /dev/null
+++ b/cfe/cfe/include/lib_malloc.h
@@ -0,0 +1,78 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Local memory manager File: mempool.h
+ *
+ * This routine is used to manage memory allocated within the
+ * firmware. You give it a chunk of memory to manage, and then
+ * these routines manage suballocations from there.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifndef _LIB_MALLOC_H
+#define _LIB_MALLOC_H
+
+typedef struct memstats_s {
+ int mem_totalbytes;
+ int mem_allocbytes;
+ int mem_freebytes;
+ int mem_allocnodes;
+ int mem_freenodes;
+ int mem_largest;
+} memstats_t;
+
+typedef struct mempool_s mempool_t;
+void kmeminit(mempool_t *pool,unsigned char *buffer,int length);
+void kfree(mempool_t *pool,void *ptr);
+void *kmalloc(mempool_t *pool,unsigned int size,unsigned int align);
+int kmemchk(mempool_t *pool,int verbose);
+extern mempool_t kmempool;
+void *kmempoolbase(mempool_t *pool);
+int kmempoolsize(mempool_t *pool);
+int kmemstats(mempool_t *pool,memstats_t *stats);
+
+#define KMEMINIT(buffer,length) kmeminit(&kmempool,(buffer),(length))
+#define KMEMPOOLBASE() kmempoolbase(&kmempool)
+#define KMEMPOOLSIZE() kmempoolsize(&kmempool)
+#define KMALLOC(size,align) kmalloc(&kmempool,(size),(align))
+#define KFREE(ptr) kfree(&kmempool,(ptr))
+#define KMEMSTATS(s) kmemstats(&kmempool,(s))
+
+#endif
diff --git a/cfe/cfe/include/lib_printf.h b/cfe/cfe/include/lib_printf.h
new file mode 100755
index 0000000..e4d2860
--- /dev/null
+++ b/cfe/cfe/include/lib_printf.h
@@ -0,0 +1,69 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * simple printf File: lib_printf.h
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ * This module contains a very, very, very simple printf
+ * suitable for use in the boot ROM.
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include <stdarg.h>
+
+int xvsprintf(char *outbuf,const char *templat,va_list marker);
+int xsprintf(char *buf,const char *templat,...);
+#if CFG_RAMAPP
+int xprintf(const char *templat,...);
+#else
+#define xprintf(...)
+#endif
+
+extern int (*xprinthook)(const char *);
+int xvprintf(const char *template,va_list marker);
+
+/*
+ * compatibility macros
+ */
+
+
+#define printf xprintf
+#define sprintf xsprintf
+#define vsprintf xvsprintf
+#define vprintf xvprintf
diff --git a/cfe/cfe/include/lib_queue.h b/cfe/cfe/include/lib_queue.h
new file mode 100644
index 0000000..530c70f
--- /dev/null
+++ b/cfe/cfe/include/lib_queue.h
@@ -0,0 +1,85 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Queue management prototypes File: lib_queue.h
+ *
+ * Constants, structures, and function prototypes for the queue
+ * manager.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#ifndef _LIB_QUEUE_H
+#define _LIB_QUEUE_H
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define q_init(q) (q)->q_prev = (q), (q)->q_next = (q)
+#define q_isempty(q) ((q)->q_next == (q))
+#define q_getfirst(q) ((q)->q_next)
+#define q_getlast(q) ((q)->q_prev)
+
+/* *********************************************************************
+ * Types
+ ********************************************************************* */
+
+
+typedef struct queue_s {
+ struct queue_s *q_next;
+ struct queue_s *q_prev;
+} queue_t;
+
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+void q_enqueue(queue_t *,queue_t *);
+void q_dequeue(queue_t *);
+queue_t *q_deqnext(queue_t *);
+int q_map(queue_t *qb,int (*func)(queue_t *,unsigned int,unsigned int),
+ unsigned int a,unsigned int b);
+int q_count(queue_t *);
+int q_find(queue_t *,queue_t *);
+
+
+#endif
diff --git a/cfe/cfe/include/lib_string.h b/cfe/cfe/include/lib_string.h
new file mode 100644
index 0000000..4d0f3d8
--- /dev/null
+++ b/cfe/cfe/include/lib_string.h
@@ -0,0 +1,117 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * string prototypes File: lib_string.h
+ *
+ * Function prototypes for the string routines
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+char *lib_strcpy(char *dest,const char *src);
+char *lib_strncpy(char *dest,const char *src,size_t cnt);
+size_t lib_xstrncpy(char *dest,const char *src,size_t cnt);
+size_t lib_strlen(const char *str);
+
+int lib_strcmp(const char *dest,const char *src);
+
+/* Foxconn add start by Cliff Wang, 03/23/2010 */
+int lib_strncmp(const char *dest, const char *src, size_t cnt );
+/* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+int lib_strcmpi(const char *dest,const char *src);
+char *lib_strchr(const char *dest,int c);
+char *lib_strrchr(const char *dest,int c);
+int lib_memcmp(const void *dest,const void *src,size_t cnt);
+void *lib_memcpy(void *dest,const void *src,size_t cnt);
+void *lib_memset(void *dest,int c,size_t cnt);
+char *lib_strdup(char *str);
+void lib_trimleading(char *str);
+void lib_chop_filename(char *str,char **host,char **file);
+void lib_strupr(char *s);
+char lib_toupper(char c);
+char *lib_strcat(char *dest,const char *src);
+char *lib_gettoken(char **str);
+char *lib_strnchr(const char *dest,int c,size_t cnt);
+int lib_parseipaddr(const char *ipaddr,uint8_t *dest);
+int lib_atoi(const char *dest);
+int lib_lookup(const cons_t *list,char *str);
+int lib_setoptions(const cons_t *list,char *str,unsigned int *flags);
+int lib_xtoi(const char *dest);
+uint64_t lib_xtoq(const char *dest);
+
+
+
+#ifndef _LIB_NO_MACROS_
+#define strcpy(d,s) lib_strcpy(d,s)
+#define strncpy(d,s,c) lib_strncpy(d,s,c)
+#define xstrncpy(d,s,c) lib_xstrncpy(d,s,c)
+#define strlen(s) lib_strlen(s)
+#define strchr(s,c) lib_strchr(s,c)
+#define strrchr(s,c) lib_strrchr(s,c)
+#define strdup(s) lib_strdup(s)
+#define strcmp(d,s) lib_strcmp(d,s)
+
+/* Foxconn add start by Cliff Wang, 03/23/2010 */
+#define strncmp(d,s,c) lib_strncmp(d,s,c)
+/* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+#define strcmpi(d,s) lib_strcmpi(d,s)
+#define memcmp(d,s,c) lib_memcmp(d,s,c)
+#define memset(d,s,c) lib_memset(d,s,c)
+#define memcpy(d,s,c) lib_memcpy(d,s,c)
+#define bcopy(s,d,c) lib_memcpy(d,s,c)
+#define bzero(d,c) lib_memset(d,0,c)
+#define strupr(s) lib_strupr(s)
+#define toupper(c) lib_toupper(c)
+#define strcat(d,s) lib_strcat(d,s)
+#define gettoken(s) lib_gettoken(s)
+#define strnchr(d,ch,cnt) lib_strnchr(d,ch,cnt)
+#define atoi(d) lib_atoi(d)
+#define xtoi(d) lib_xtoi(d)
+#define xtoq(d) lib_xtoq(d)
+#define parseipaddr(i,d) lib_parseipaddr(i,d)
+#define lookup(x,y) lib_lookup(x,y)
+#define setoptions(x,y,z) lib_setoptions(x,y,z)
+#endif
+
+void
+qsort(void *bot, size_t nmemb, size_t size, int (*compar)(const void *,const void *));
+
diff --git a/cfe/cfe/include/lib_types.h b/cfe/cfe/include/lib_types.h
new file mode 100644
index 0000000..7453a0d
--- /dev/null
+++ b/cfe/cfe/include/lib_types.h
@@ -0,0 +1,120 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Basic types File: lib_types.h
+ *
+ * This module defines the basic types used in CFE. Simple
+ * types, such as uint64_t, are defined here.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#ifdef __mips
+#if ((defined(__MIPSEB)+defined(__MIPSEL)) != 1)
+#error "Either __MIPSEB or __MIPSEL must be defined!"
+#endif
+#endif
+
+
+#ifndef _LIB_TYPES_H
+#define _LIB_TYPES_H
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/* *********************************************************************
+ * Basic types
+ ********************************************************************* */
+
+typedef int size_t;
+
+typedef char int8_t;
+typedef unsigned char uint8_t;
+
+typedef short int16_t;
+typedef unsigned short uint16_t;
+
+#ifdef __long64
+typedef int int32_t;
+typedef unsigned int uint32_t;
+#else
+typedef long int32_t;
+typedef unsigned long uint32_t;
+#endif
+
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+
+#define unsigned signed /* Kludge to get unsigned size-shaped type. */
+typedef __SIZE_TYPE__ intptr_t;
+#undef unsigned
+typedef __SIZE_TYPE__ uintptr_t;
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#ifndef offsetof
+#define offsetof(type,memb) ((size_t)&((type *)0)->memb)
+#endif
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef struct cons_s {
+ char *str;
+ int num;
+} cons_t;
+
+#endif
diff --git a/cfe/cfe/include/socregs.h b/cfe/cfe/include/socregs.h
new file mode 100644
index 0000000..835f8aa
--- /dev/null
+++ b/cfe/cfe/include/socregs.h
@@ -0,0 +1,63 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * SOC Register table defs File: socregs.h
+ *
+ * Data structures related to the "show soc" command and the
+ * "makereg" program.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+typedef struct socreg_s socreg_t;
+
+struct socreg_s {
+ uint32_t reg_addr;
+ uint32_t reg_agent;
+ const char *reg_inst;
+ const char *reg_subinst;
+ uint32_t reg_mask;
+ void (*reg_printfunc)(const socreg_t *reg,uint64_t value);
+ const char *reg_descr;
+};
+
+
+
+
diff --git a/cfe/cfe/include/tftpd.h b/cfe/cfe/include/tftpd.h
new file mode 100755
index 0000000..d7a15a9
--- /dev/null
+++ b/cfe/cfe/include/tftpd.h
@@ -0,0 +1,26 @@
+/***************************************************************************
+***
+*** Copyright 2005 Hon Hai Precision Ind. Co. Ltd.
+*** All Rights Reserved.
+*** No portions of this material shall be reproduced in any form without the
+*** written permission of Hon Hai Precision Ind. Co. Ltd.
+***
+*** All information contained in this document is Hon Hai Precision Ind.
+*** Co. Ltd. company private, proprietary, and trade secret property and
+*** are protected by international intellectual property laws and treaties.
+***
+****************************************************************************/
+
+#ifndef __TFTPD_H
+#define __TFTPD_H
+
+/* Foxconn add start by Cliff Wang, 03/23/2010 */
+#define TFTPD_STATE_OFF 0
+#define TFTPD_STATE_WAIT_IMAGE 1
+#define TFTPD_STATE_WRITE_IMAGE 2
+
+extern int get_tftpd_state(void);
+extern int set_tftpd_state(int state);
+/* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+#endif
diff --git a/cfe/cfe/include/ui_command.h b/cfe/cfe/include/ui_command.h
new file mode 100644
index 0000000..e85a3ae
--- /dev/null
+++ b/cfe/cfe/include/ui_command.h
@@ -0,0 +1,140 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Command interpreter defs File: ui_command.h
+ *
+ * This file contains structures related to the
+ * command interpreter.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifndef _LIB_QUEUE_H
+#include "lib_queue.h"
+#endif
+
+typedef struct ui_cmdsw_s {
+ int swidx;
+ char *swname;
+ char *swvalue;
+} ui_cmdsw_t;
+
+#define MAX_TOKENS 64
+#define MAX_SWITCHES 16
+#define MAX_TOKEN_SIZE 1000
+typedef struct ui_cmdline_s {
+ int argc;
+ char *argv[MAX_TOKENS];
+ int swc;
+ ui_cmdsw_t swv[MAX_SWITCHES];
+ int (*func)(struct ui_cmdline_s *,int argc,char *argv[]);
+ int argidx;
+ char *ref;
+ char *usage;
+ char *switches;
+} ui_cmdline_t;
+
+typedef struct ui_command_s {
+ queue_t list;
+ int term;
+ char *ptr;
+ queue_t head;
+} ui_command_t;
+
+typedef struct ui_token_s {
+ queue_t qb;
+ char token;
+} ui_token_t;
+
+#define CMD_TERM_EOL 0
+#define CMD_TERM_SEMI 1
+#define CMD_TERM_AND 2
+#define CMD_TERM_OR 3
+
+int cmd_sw_value(ui_cmdline_t *cmd,char *swname,char **swvalue);
+int cmd_sw_posn(ui_cmdline_t *cmd,char *swname);
+char *cmd_sw_name(ui_cmdline_t *cmd,int swidx);
+int cmd_sw_isset(ui_cmdline_t *cmd,char *swname);
+char *cmd_getarg(ui_cmdline_t *cmd,int argnum);
+void cmd_free(ui_cmdline_t *cmd);
+int cmd_sw_validate(ui_cmdline_t *cmd,char *validstr);
+void cmd_parse(ui_cmdline_t *cmd,char *line);
+int cmd_addcmd(char *command,
+ int (*func)(ui_cmdline_t *,int argc,char *argv[]),
+ void *ref,
+ char *help,
+ char *usage,
+ char *switches);
+int cmd_lookup(queue_t *head,ui_cmdline_t *cmd);
+void cmd_init(void);
+int cmd_getcommand(ui_cmdline_t *cmd);
+void cmd_showusage(ui_cmdline_t *cmd);
+
+
+
+#define CMD_ERR_INVALID -1
+#define CMD_ERR_AMBIGUOUS -2
+#define CMD_ERR_BLANK -3
+
+
+/* *********************************************************************
+ * Prototypes (public routines)
+ ********************************************************************* */
+
+const char *ui_errstring(int errcode);
+int ui_showerror(int errcode,char *tmplt,...);
+int ui_showusage(ui_cmdline_t *cmd);
+int ui_docommands(char *str);
+#define ui_docommand(str) ui_docommands(str)
+void ui_restart(int);
+int ui_init_cmddisp(void);
+
+
+/* *********************************************************************
+ * Prototypes (internal routines)
+ ********************************************************************* */
+
+ui_command_t *cmd_readcommand(queue_t *head);
+void cmd_build_list(queue_t *qb,char *buf);
+void cmd_walk_and_expand(queue_t *qb);
+ui_command_t *cmd_readcommand(queue_t *head);
+void cmd_free_tokens(queue_t *list);
+void cmd_build_cmdline(queue_t *head, ui_cmdline_t *cmd);
+
+
diff --git a/cfe/cfe/lib/lib_arena.c b/cfe/cfe/lib/lib_arena.c
new file mode 100644
index 0000000..41867dc
--- /dev/null
+++ b/cfe/cfe/lib/lib_arena.c
@@ -0,0 +1,389 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Arena Manager File lib_arena.c
+ *
+ * This module manages the _arena_, a sorted linked list of
+ * memory regions and attributes. We use this to keep track
+ * of physical memory regions and what is assigned to them.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_queue.h"
+#include "lib_arena.h"
+#include "lib_malloc.h"
+
+/* *********************************************************************
+ * arena_print(arena,msg)
+ *
+ * Debug routine to print out an arena entry
+ *
+ * Input parameters:
+ * arena - arena descriptor
+ * msg - heading message
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+#ifdef _TESTPROG_
+static void arena_print(arena_t *arena,char *msg)
+{
+ arena_node_t *node;
+ queue_t *qb;
+
+ printf("%s\n",msg);
+
+ for (qb = (arena->arena_list.q_next); qb != &(arena->arena_list);
+ qb = qb->q_next) {
+ node = (arena_node_t *) qb;
+
+ printf("Start %5I64d End %5I64d Type %d\n",
+ node->an_address,
+ node->an_address+node->an_length,
+ node->an_type);
+
+ }
+
+}
+#endif
+
+/* *********************************************************************
+ * arena_init(arena,physmembase,physmemsize)
+ *
+ * Initialize an arena descriptor. The arena is typically
+ * created to describe the entire physical memory address space.
+ *
+ * Input parameters:
+ * arena - arena descriptor
+ * physmembase - base of region to manage (usually 0)
+ * physmemsize - size of region to manage (typically maxint)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void arena_init(arena_t *arena,uint64_t physmembase,uint64_t physmemsize)
+{
+ arena_node_t *an = NULL;
+
+ an = (arena_node_t *) KMALLOC(sizeof(arena_node_t),sizeof(uint64_t));
+
+ /* XXX check return value */
+
+ arena->arena_base = physmembase;
+ arena->arena_size = physmemsize;
+
+ an->an_address = physmembase;
+ an->an_length = physmemsize;
+ an->an_type = 0;
+ an->an_descr = NULL;
+
+ q_init(&(arena->arena_list));
+ q_enqueue(&(arena->arena_list),(queue_t *) an);
+}
+
+
+/* *********************************************************************
+ * arena_find(arena,pt)
+ *
+ * Locate the arena node containing a particular point in the
+ * address space. This routine walks the list and finds the node
+ * whose address range contains the specified point.
+ *
+ * Input parameters:
+ * arena - arena descriptor
+ * pt - point to look for
+ *
+ * Return value:
+ * arena node pointer, or NULL if no node found
+ ********************************************************************* */
+
+static arena_node_t *arena_find(arena_t *arena,uint64_t pt)
+{
+ queue_t *qb;
+ arena_node_t *an;
+
+ for (qb = (arena->arena_list.q_next); qb != &(arena->arena_list);
+ qb = qb->q_next) {
+ an = (arena_node_t *) qb;
+
+ if ((pt >= an->an_address) &&
+ (pt < (an->an_address + an->an_length))) return an;
+
+ }
+
+ return NULL;
+}
+
+/* *********************************************************************
+ * arena_split(arena,splitpoint)
+ *
+ * Split the node containing the specified point. When we carve
+ * the arena up, we split the arena at the points on the edges
+ * of the new region, change their types, and then coalesce the
+ * arena. This handles the "split" part of that process.
+ *
+ * Input parameters:
+ * arena - arena descriptor
+ * splitpoint - address to split arena at
+ *
+ * Return value:
+ * 0 if ok
+ * -1 if could not split
+ ********************************************************************* */
+
+static int arena_split(arena_t *arena,uint64_t splitpoint)
+{
+ arena_node_t *node;
+ arena_node_t *newnode;
+
+ /*
+ * Don't need to split if it's the *last* address in the arena
+ */
+
+ if (splitpoint == (arena->arena_base+arena->arena_size)) return 0;
+
+ /*
+ * Find the block that contains the split point.
+ */
+
+ node = arena_find(arena,splitpoint);
+ if (node == NULL) return -1; /* should not happen */
+
+ /*
+ * If the address matches exactly, don't need to split
+ */
+ if (node->an_address == splitpoint) return 0;
+
+ /*
+ * Allocate a new node and adjust the length of the node we're
+ * splitting.
+ */
+
+ newnode = (arena_node_t *) KMALLOC(sizeof(arena_node_t),sizeof(uint64_t));
+
+ newnode->an_length = node->an_length - (splitpoint - node->an_address);
+ node->an_length = splitpoint - node->an_address;
+ newnode->an_address = splitpoint;
+ newnode->an_type = node->an_type;
+
+ /*
+ * Put the new node in the arena
+ */
+
+ q_enqueue(node->an_next.q_next,(queue_t *) newnode);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * arena_coalesce(arena)
+ *
+ * Coalesce the arena, merging regions that have the same type
+ * together. After coalescing, no two adjacent nodes will
+ * have the same type.
+ *
+ * Input parameters:
+ * arena - arena descriptor
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void arena_coalesce(arena_t *arena)
+{
+ arena_node_t *node;
+ arena_node_t *nextnode;
+ int removed;
+ queue_t *qb;
+
+ do {
+ removed = 0;
+ for (qb = (arena->arena_list.q_next); qb != &(arena->arena_list);
+ qb = qb->q_next) {
+
+ node = (arena_node_t *) qb;
+ nextnode = (arena_node_t *) node->an_next.q_next;
+
+ if ((queue_t *) nextnode == &(arena->arena_list)) break;
+
+ if (node->an_type == nextnode->an_type) {
+ node->an_length += nextnode->an_length;
+ q_dequeue((queue_t *) nextnode);
+ KFREE(nextnode);
+ removed++;
+ }
+ }
+ } while (removed > 0);
+}
+
+
+/* *********************************************************************
+ * arena_markrange(arena,address,length,type,descr)
+ *
+ * Mark a region in the arena, changing the types of nodes and
+ * splitting nodes as necessary. This routine is called for
+ * each region we want to add. The order of marking regions is
+ * important, since new marks overwrite old ones. Therefore, you
+ * could mark a whole range as DRAM, and then mark sub-regions
+ * within that as used by firmware.
+ *
+ * Input parameters:
+ * arena - arena descriptor
+ * address,length - region to mark
+ * type - type code for region
+ * descr - text description of region (optional)
+ *
+ * Return value:
+ * 0 if ok
+ * -1 if error
+ ********************************************************************* */
+
+int arena_markrange(arena_t *arena,uint64_t address,uint64_t length,int type,char *descr)
+{
+ queue_t *qb;
+ arena_node_t *node;
+
+ /*
+ * Range check the region we want to mark
+ */
+
+ if ((address < arena->arena_base) ||
+ ((address+length) > (arena->arena_base + arena->arena_size))) {
+ return -1;
+ }
+
+ /*
+ * Force the arena to be split at the two points at the
+ * beginning and end of the range we want. If we have
+ * problems, coalesce the arena again and get out.
+ */
+
+ if (arena_split(arena,address) < 0) {
+ /* don't need to coalesce, we didn't split */
+ return -1;
+ }
+ if (arena_split(arena,(address+length)) < 0) {
+ /* recombine nodes split above */
+ arena_coalesce(arena);
+ return -1;
+ }
+
+ /*
+ * Assuming we've split the arena at the beginning and ending
+ * split points, we'll never mark any places outside the range
+ * specified in the "Address,length" args.
+ */
+
+ for (qb = (arena->arena_list.q_next); qb != &(arena->arena_list);
+ qb = qb->q_next) {
+ node = (arena_node_t *) qb;
+
+ if ((node->an_address >= address) &&
+ ((node->an_address + node->an_length) <= (address+length))) {
+ node->an_type = type;
+ node->an_descr = descr;
+ }
+ }
+
+ /*
+ * Now, coalesce adjacent pieces with the same type back together again
+ */
+
+ arena_coalesce(arena);
+
+ return 0;
+}
+
+
+
+/* *********************************************************************
+ * main(argc,argv)
+ *
+ * Test program.
+ *
+ * Input parameters:
+ * argc,argv - guess
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+#ifdef _TESTPROG_
+void main(int argc,char *argv[])
+{
+ arena_t arena;
+
+ arena_init(&arena,0,1024);
+#if 0
+ arena_print(&arena,"empty arena------------");
+
+ arena_split(&arena,5);
+ arena_print(&arena,"split at 5-------------");
+
+ arena_split(&arena,300);
+ arena_print(&arena,"split at 300-----------");
+
+ arena_split(&arena,100);
+ arena_print(&arena,"split at 100-----------");
+
+ arena_coalesce(&arena);
+ arena_print(&arena,"coalesced again--------");
+
+ arena_markrange(&arena,100,50,1);
+ arena_print(&arena,"addrange 100-150-------");
+ arena_markrange(&arena,10,50,1);
+ arena_print(&arena,"addrange 10-60---------");
+ arena_markrange(&arena,1000,24,3);
+ arena_print(&arena,"addrange 1000-1023-----");
+#endif
+
+ arena_markrange(&arena,100,10,1);
+ arena_markrange(&arena,120,10,2);
+ arena_markrange(&arena,140,10,3);
+ arena_print(&arena,"Before big markrange---------");
+
+ arena_markrange(&arena,50,200,4);
+ arena_print(&arena,"after big markrange---------");
+
+}
+#endif
diff --git a/cfe/cfe/lib/lib_malloc.c b/cfe/cfe/lib/lib_malloc.c
new file mode 100644
index 0000000..f7e33b2
--- /dev/null
+++ b/cfe/cfe/lib/lib_malloc.c
@@ -0,0 +1,620 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Local memory manager File: cfe_malloc.c
+ *
+ * This routine is used to manage memory allocated within the
+ * firmware. You give it a chunk of memory to manage, and then
+ * these routines manage suballocations from there.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifdef TESTPROG
+#include <stdio.h>
+#include <malloc.h>
+#include <stdlib.h>
+#endif
+
+#include "lib_types.h"
+#include "lib_printf.h"
+#include "lib_malloc.h"
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define MEMNODE_SEAL 0xFAAFA123 /* just some random constant */
+#define MINBLKSIZE 64
+
+/* *********************************************************************
+ * Types
+ ********************************************************************* */
+
+typedef enum { memnode_free = 0, memnode_alloc } memnode_status_t;
+
+typedef struct memnode_s {
+ unsigned int seal;
+ struct memnode_s *next; /* pointer to next node */
+ unsigned int length; /* length of the entire data section */
+ memnode_status_t status; /* alloc/free status */
+ unsigned char *data; /* points to actual user data */
+ void *memnodeptr; /* memnode back pointer (see comments) */
+} memnode_t;
+
+struct mempool_s {
+ memnode_t *root; /* pointer to root node */
+ unsigned char *base; /* base of memory region */
+ unsigned int length; /* size of memory region */
+};
+
+#define memnode_data(t,m) (t) (((memnode_t *) (m))+1)
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+mempool_t kmempool; /* default pool */
+
+/* *********************************************************************
+ * kmeminit(pool,buffer,length)
+ *
+ * Initialize the memory manager, given a pointer to an area
+ * of memory and a size. This routine simply initializes the
+ * root node to be a single block of empty space.
+ *
+ * Input parameters:
+ * pool - pool pointer
+ * buffer - beginning of buffer area, must be pointer-aligned
+ * length - length of buffer area
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+void kmeminit(mempool_t *pool,unsigned char *buffer,int length)
+{
+ pool->root = (memnode_t *) buffer;
+ pool->root->seal = MEMNODE_SEAL;
+ pool->root->length = length - sizeof(memnode_t);
+ pool->root->data = memnode_data(unsigned char *,pool->root);
+ pool->root->status = memnode_free;
+ pool->root->next = NULL;
+
+ pool->base = buffer;
+ pool->length = length;
+}
+
+
+/* *********************************************************************
+ * kmempoolbase(pool)
+ *
+ * Returns the base address of the specified memory pool
+ *
+ * Input parameters:
+ * pool - pool pointer
+ *
+ * Return value:
+ * pointer to beginning of pool's memory
+ ********************************************************************* */
+void *kmempoolbase(mempool_t *pool)
+{
+ return pool->base;
+}
+
+/* *********************************************************************
+ * kmempoolsize(pool)
+ *
+ * Returns the total size of the specified memory pool
+ *
+ * Input parameters:
+ * pool - pool pointer
+ *
+ * Return value:
+ * size of pool in bytes
+ ********************************************************************* */
+
+int kmempoolsize(mempool_t *pool)
+{
+ return pool->length;
+}
+
+/* *********************************************************************
+ * kmemcompact(pool)
+ *
+ * Compact the memory blocks, coalescing consectutive free blocks
+ * on the list.
+ *
+ * Input parameters:
+ * pool - pool descriptor
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void kmemcompact(mempool_t *pool)
+{
+ memnode_t *m;
+ int compacted;
+
+ do {
+ compacted = 0;
+
+ for (m = pool->root; m; m = m->next) {
+
+ /* Check seal to be sure that we're doing ok */
+
+ if (m->seal != MEMNODE_SEAL) {
+#ifdef TESTPROG
+ printf("Memory list corrupted!\n");
+#endif
+ return;
+ }
+
+ /*
+ * If we're not on the last block and both this
+ * block and the next one are free, combine them
+ */
+
+ if (m->next &&
+ (m->status == memnode_free) &&
+ (m->next->status == memnode_free)) {
+ m->length += sizeof(memnode_t) + m->next->length;
+ m->next->seal = 0;
+ m->next = m->next->next;
+ compacted++;
+ }
+
+ /* Keep going till we make a pass without doing anything. */
+ }
+ } while (compacted > 0);
+}
+
+
+/* *********************************************************************
+ * kfree(ptr)
+ *
+ * Return some memory to the pool.
+ *
+ * Input parameters:
+ * ptr - pointer to something allocated via kmalloc()
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void kfree(mempool_t *pool,void *ptr)
+{
+ memnode_t **backptr;
+ memnode_t *m;
+
+ if (((unsigned char *) ptr < pool->base) ||
+ ((unsigned char *) ptr >= (pool->base+pool->length))) {
+#ifdef TESTPROG
+ printf("Pointer %08X does not belong to pool %08X\n",ptr,pool);
+#endif
+ return;
+ }
+
+ backptr = (memnode_t **) (((unsigned char *) ptr) - sizeof(memnode_t *));
+ m = *backptr;
+
+ if (m->seal != MEMNODE_SEAL) {
+#ifdef TESTPROG
+ printf("Invalid node freed: %08X\n",m);
+#endif
+ return;
+ }
+
+ m->status = memnode_free;
+
+ kmemcompact(pool);
+}
+
+/* *********************************************************************
+ * lib_outofmemory()
+ *
+ * Called when we run out of memory.
+ * XXX replace with something real someday
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void lib_outofmemory(void);
+void lib_outofmemory(void)
+{
+ xprintf("PANIC: out of memory!\n");
+}
+
+/* *********************************************************************
+ * kmalloc(pool,size,align)
+ *
+ * Allocate some memory from the pool.
+ *
+ * Input parameters:
+ * pool - pool structure
+ * size - size of item to allocate
+ * align - alignment (must be zero or a power of 2)
+ *
+ * Return value:
+ * pointer to data, or NULL if no memory left
+ ********************************************************************* */
+
+void *kmalloc(mempool_t *pool,unsigned int size,unsigned int align)
+{
+ memnode_t *m;
+ memnode_t *newm;
+ memnode_t **backptr;
+ uintptr_t daddr = 0;
+ uintptr_t realsize = 0;
+ uintptr_t extra;
+ uintptr_t blkend;
+ uintptr_t ptralign;
+
+ /*
+ * Everything should be aligned by at least the
+ * size of an int64
+ */
+
+ ptralign = (uintptr_t) align;
+ if (ptralign < sizeof(void *)) ptralign = sizeof(uint64_t);
+
+ /*
+ * Everything should be at least a multiple of the
+ * size of a pointer.
+ */
+
+ if (size == 0) size = sizeof(void *);
+ if (size & (sizeof(void *)-1)) {
+ size += sizeof(void *);
+ size &= ~(sizeof(void *)-1);
+ }
+
+ /*
+ * Find a memnode at least big enough to hold the storage we
+ * want.
+ */
+
+ for (m = pool->root; m; m = m->next) {
+
+ if (m->status == memnode_alloc) continue;
+
+ /*
+ * If we wanted a particular alignment, we will
+ * need to adjust the size.
+ */
+
+ daddr = memnode_data(uintptr_t,m);
+ extra = 0;
+ if (daddr & (ptralign-1)) {
+ extra = size + (ptralign - (daddr & (ptralign-1)));
+ }
+ realsize = size + extra;
+
+ if (m->length < realsize) continue;
+ break;
+ }
+
+ /*
+ * If m is null, there's no memory left.
+ */
+
+ if (m == NULL) {
+ lib_outofmemory();
+ return NULL;
+ }
+
+ /*
+ * Otherwise, use this block. Calculate the address of the data
+ * to preserve the alignment.
+ */
+
+ if (daddr & (ptralign-1)) {
+ daddr += ptralign;
+ daddr &= ~(ptralign-1);
+ }
+
+ /* Mark this node as allocated. */
+
+ m->data = (unsigned char *) daddr;
+ m->status = memnode_alloc;
+
+ /*
+ * Okay, this is ugly. Store a pointer to the original
+ * memnode just before what we've allocated. It's guaranteed
+ * to be aligned at least well enough for this pointer.
+ * If for some reason the memnode was already exactly
+ * aligned, backing up will put us inside the memnode
+ * structure itself... that's why the memnodeptr field
+ * is there, as a placeholder for this eventuality.
+ */
+
+ backptr = (memnode_t **) (m->data - sizeof(memnode_t *));
+ *backptr = m;
+
+ /*
+ * See if we need to split it.
+ * Don't bother to split if the resulting size will be
+ * less than MINBLKSIZE bytes
+ */
+
+ if (m->length - realsize < MINBLKSIZE) {
+ return m->data;
+ }
+
+ /*
+ * Split this block. Align the address on a pointer-size
+ * boundary.
+ */
+
+ daddr += size;
+ if (daddr & (uintptr_t)(sizeof(void *)-1)) {
+ daddr += (uintptr_t)sizeof(void *);
+ daddr &= ~(uintptr_t)(sizeof(void *)-1);
+ }
+
+ blkend = memnode_data(uintptr_t,m) + (uintptr_t)(m->length);
+
+ newm = (memnode_t *) daddr;
+
+ newm->next = m->next;
+ m->length = (unsigned int) (daddr - memnode_data(uintptr_t,m));
+ m->next = newm;
+ m->status = memnode_alloc;
+ newm->seal = MEMNODE_SEAL;
+ newm->data = memnode_data(unsigned char *,newm);
+ newm->length = (unsigned int) (blkend - memnode_data(uintptr_t,newm));
+ newm->status = memnode_free;
+
+ return m->data;
+}
+
+
+int kmemstats(mempool_t *pool,memstats_t *stats)
+{
+ memnode_t *m;
+ memnode_t **backptr;
+ uintptr_t daddr;
+
+ stats->mem_totalbytes = pool->length;
+ stats->mem_allocbytes = 0;
+ stats->mem_freebytes = 0;
+ stats->mem_allocnodes = 0;
+ stats->mem_freenodes = 0;
+ stats->mem_largest = 0;
+
+ for (m = pool->root; m; m = m->next) {
+ if (m->status) {
+ stats->mem_allocnodes++;
+ stats->mem_allocbytes += m->length;
+ }
+ else {
+ stats->mem_freenodes++;
+ stats->mem_freebytes += m->length;
+ if (m->length > stats->mem_largest) {
+ stats->mem_largest = m->length;
+ }
+ }
+
+ daddr = memnode_data(uintptr_t,m);
+ if (m->seal != MEMNODE_SEAL) {
+ return -1;
+ }
+ if (m->next && ((daddr + m->length) != (uintptr_t) m->next)) {
+ return -1;
+ }
+ if (m->next && (m->next < m)) {
+ return -1;
+ }
+ if (m->data < (unsigned char *) m) {
+ return -1;
+ }
+ if (m->status == memnode_alloc) {
+ backptr = (memnode_t **) (m->data - sizeof(void *));
+ if (*backptr != m) {
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * kmemchk()
+ *
+ * Check the consistency of the memory pool.
+ *
+ * Input parameters:
+ * pool - pool pointer
+ *
+ * Return value:
+ * 0 - pool is consistent
+ * -1 - pool is corrupt
+ ********************************************************************* */
+
+#ifdef TESTPROG
+int kmemchk(mempool_t *pool,int verbose)
+{
+ memnode_t *m;
+ memnode_t **backptr;
+ unsigned int daddr;
+
+ for (m = pool->root; m; m = m->next) {
+ if (verbose) {
+ printf("%08X: Next=%08X Len=%5u %s Data=%08X ",
+ m,m->next,m->length,
+ m->status ? "alloc" : "free ",
+ m->data);
+ }
+ daddr = memnode_data(uintptr_t,m);
+ if (m->seal != MEMNODE_SEAL) {
+ if (verbose) printf("BadSeal ");
+ else return -1;
+ }
+ if (m->next && (daddr + m->length != (unsigned int) m->next)) {
+ if (verbose) printf("BadLength ");
+ else return -1;
+ }
+ if (m->next && (m->next < m)) {
+ if (verbose) printf("BadOrder ");
+ else return -1;
+ }
+ if (m->data < (unsigned char *) m) {
+ if (verbose) printf("BadData ");
+ else return -1;
+ }
+ if (m->status == memnode_alloc) {
+ backptr = (memnode_t **) (m->data - sizeof(void *));
+ if (*backptr != m) {
+ if (verbose) printf("BadBackPtr ");
+ else return -1;
+ }
+ }
+ if (verbose) printf("\n");
+ }
+
+ return 0;
+}
+
+
+#define MEMSIZE 1024*1024
+
+unsigned char *ptrs[4096];
+unsigned int sizes[4096];
+
+/* *********************************************************************
+ * main(argc,argv)
+ *
+ * Test program for the memory allocator
+ *
+ * Input parameters:
+ * argc,argv
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+void main(int argc,char *argv[])
+{
+ unsigned char *mem;
+ int items = 0;
+ int idx;
+ int size;
+ int totalsize = 0;
+ int nfree,freecnt;
+ mempool_t *pool = &kmempool;
+
+ mem = malloc(MEMSIZE);
+ kmeminit(pool,mem,MEMSIZE);
+
+ items = 0;
+
+ for (;;) {
+
+ for (;;) {
+ if (items == 4096) break;
+ size = rand() % 1024;
+ ptrs[items] = kmalloc(pool,size,1<<(rand() & 7));
+ if (!ptrs[items]) break;
+ sizes[items] = size;
+ items++;
+ totalsize += size;
+ }
+
+ printf("%d items allocated, %d total bytes\n",items,totalsize);
+
+ if (kmemchk(pool,0) < 0) {
+ kmemchk(pool,1);
+ exit(1);
+ }
+
+ /* Scramble the pointers */
+ idx = items - 1;
+
+ while (idx) {
+ if (rand() & 2) {
+ mem = ptrs[0];
+ ptrs[0] = ptrs[idx];
+ ptrs[idx] = mem;
+
+ nfree = sizes[0];
+ sizes[0] = sizes[idx];
+ sizes[idx] = nfree;
+ }
+ idx--;
+ }
+
+ /* now free a random number of elements */
+
+ nfree = rand() % items;
+ freecnt = 0;
+
+ for (idx = nfree; idx < items; idx++) {
+ kfree(pool,ptrs[idx]);
+ totalsize -= sizes[idx];
+ freecnt++;
+ ptrs[idx] = NULL;
+ sizes[idx] = 0;
+ if (kmemchk(pool,0) < 0) {
+ kmemchk(pool,1);
+ exit(1);
+ }
+ }
+
+ items -= freecnt;
+
+ printf(".");
+
+ }
+
+ kmemchk(pool,1);
+
+ exit(0);
+}
+
+#endif /* TESTPROG */
diff --git a/cfe/cfe/lib/lib_misc.c b/cfe/cfe/lib/lib_misc.c
new file mode 100644
index 0000000..e5a2a02
--- /dev/null
+++ b/cfe/cfe/lib/lib_misc.c
@@ -0,0 +1,229 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Misc. library routines File: lib_misc.c
+ *
+ * Miscellaneous library routines.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#define _LIB_NO_MACROS_
+#include "lib_string.h"
+
+
+/* *********************************************************************
+ * lib_parseipaddr(ipaddr,dest)
+ *
+ * Parse an IP address.
+ *
+ * Input parameters:
+ * ipaddr - string of IP address
+ * dest - pointer to 4 bytes to receive binary IP address
+ *
+ * Return value:
+ * 0 if ok
+ * -1 if ip address is invalid
+ ********************************************************************* */
+
+int lib_parseipaddr(const char *ipaddr,uint8_t *dest)
+{
+ int a,b,c,d;
+ char *x;
+
+ /* make sure it's all digits and dots. */
+ x = (char *) ipaddr;
+ while (*x) {
+ if ((*x == '.') || ((*x >= '0') && (*x <= '9'))) {
+ x++;
+ continue;
+ }
+ return -1;
+ }
+
+ x = (char *) ipaddr;
+ a = lib_atoi(ipaddr);
+ x = lib_strchr(x,'.');
+ if (!x) return -1;
+ b = lib_atoi(x+1);
+ x = lib_strchr(x+1,'.');
+ if (!x) return -1;
+ c = lib_atoi(x+1);
+ x = lib_strchr(x+1,'.');
+ if (!x) return -1;
+ d = lib_atoi(x+1);
+
+ if ((a < 0) || (a > 255)) return -1;
+ if ((b < 0) || (b > 255)) return -1;
+ if ((c < 0) || (c > 255)) return -1;
+ if ((d < 0) || (d > 255)) return -1;
+
+ dest[0] = (uint8_t) a;
+ dest[1] = (uint8_t) b;
+ dest[2] = (uint8_t) c;
+ dest[3] = (uint8_t) d;
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * lib_lookup(list,str)
+ *
+ * Look up an element on a {string,value} list.
+ *
+ * Input parameters:
+ * list - list to search
+ * str - string to find on the list
+ *
+ * Return value:
+ * 0 if string was not found
+ * else number associated with this string
+ ********************************************************************* */
+
+int lib_lookup(const cons_t *list,char *str)
+{
+ while (list->str) {
+ if (lib_strcmp(list->str,str) == 0) return list->num;
+ list++;
+ }
+
+ return 0;
+
+}
+
+/* *********************************************************************
+ * lib_findinlist(list,str)
+ *
+ * Like lib_lookup but returns cons structure instead of value
+ *
+ * Input parameters:
+ * list - list of associations
+ * str - what to find
+ *
+ * Return value:
+ * cons_t or null if not found
+ ********************************************************************* */
+
+static const cons_t *lib_findinlist(const cons_t *list,char *str)
+{
+ while (list->str) {
+ if (lib_strcmp(list->str,str) == 0) return list;
+ list++;
+ }
+ return NULL;
+}
+
+
+/* *********************************************************************
+ * lib_setoptions(list,str,flags)
+ *
+ * Set or reset one or more bits in a flags variable based
+ * on the list of valid bits and a string containing what
+ * to change. flags starts off as a default value.
+ *
+ * The input string is a comma-separated list of options,
+ * optionally prefixed by "no_" or "no" to invert the
+ * sense of the option. negative values in the table
+ * remove options, positive add options (you can't use
+ * bit 31 as an option for this reason).
+ *
+ * Input parameters:
+ * list - list of valid options
+ * str - options to parse
+ * flags - pointer to variable to be modified
+ *
+ * Return value:
+ * number of options we did not understand, 0=ok
+ ********************************************************************* */
+
+int lib_setoptions(const cons_t *list,char *str,unsigned int *flags)
+{
+ char *dupstr;
+ char *x;
+ char *ptr;
+ const cons_t *val;
+ int newbits;
+ int errors = 0;
+
+ if (!list || !str || !flags) return 0;
+
+ dupstr = lib_strdup(str);
+ if (!dupstr) return 0;
+
+ ptr = dupstr;
+
+ while (*ptr) {
+ if ((x = lib_strchr(ptr,','))) {
+ *x = '\0';
+ }
+
+ val = lib_findinlist(list,ptr);
+ newbits = 0;
+ if (!val) {
+ if (lib_memcmp(ptr,"no_",3) == 0) {
+ val = lib_findinlist(list,ptr+3);
+ }
+ else if (lib_memcmp(ptr,"no",2) == 0) {
+ val = lib_findinlist(list,ptr+2);
+ }
+ if (val) newbits = ~((unsigned int) (val->num));
+ else errors++;
+ }
+ else {
+ newbits = (val->num);
+ }
+
+ /* if new bits are negative, it's an AND mask
+ otherwise it's an OR mask */
+
+ if (newbits < 0) *flags &= (unsigned int) newbits;
+ else *flags |= (unsigned int) newbits;
+
+ if (x) ptr = x+1;
+ else break;
+ }
+
+ KFREE(dupstr);
+
+ return errors;
+}
diff --git a/cfe/cfe/lib/lib_printf.c b/cfe/cfe/lib/lib_printf.c
new file mode 100644
index 0000000..7dc3442
--- /dev/null
+++ b/cfe/cfe/lib/lib_printf.c
@@ -0,0 +1,442 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * simple printf File: lib_printf.c
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ * This module contains a very, very, very simple printf
+ * suitable for use in the boot ROM.
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include <stdarg.h>
+#include "lib_types.h"
+#include "lib_printf.h"
+
+/* *********************************************************************
+ * Externs *
+ ********************************************************************* */
+
+/* *********************************************************************
+ * Globals *
+ ********************************************************************* */
+
+static const char digits[17] = "0123456789ABCDEF";
+static const char ldigits[17] = "0123456789abcdef";
+
+int (*xprinthook)(const char *str) = NULL;
+
+/* *********************************************************************
+ * __atox(buf,num,radix,width)
+ *
+ * Convert a number to a string
+ *
+ * Input Parameters:
+ * buf - where to put characters
+ * num - number to convert
+ * radix - radix to convert number to (usually 10 or 16)
+ * width - width in characters
+ *
+ * Return Value:
+ * number of digits placed in output buffer
+ ********************************************************************* */
+static int __atox(char *buf,unsigned int num,unsigned int radix,int width,
+ const char *digits)
+{
+ char buffer[16];
+ char *op;
+ int retval;
+
+ op = &buffer[0];
+ retval = 0;
+
+ do {
+ *op++ = digits[num % radix];
+ retval++;
+ num /= radix;
+ } while (num != 0);
+
+ if (width && (width > retval)) {
+ width = width - retval;
+ while (width) {
+ *op++ = '0';
+ retval++;
+ width--;
+ }
+ }
+
+ while (op != buffer) {
+ op--;
+ *buf++ = *op;
+ }
+
+ return retval;
+}
+
+
+/* *********************************************************************
+ * __llatox(buf,num,radix,width)
+ *
+ * Convert a long number to a string
+ *
+ * Input Parameters:
+ * buf - where to put characters
+ * num - number to convert
+ * radix - radix to convert number to (usually 10 or 16)
+ * width - width in characters
+ *
+ * Return Value:
+ * number of digits placed in output buffer
+ ********************************************************************* */
+static int __llatox(char *buf,unsigned long long num,unsigned int radix,
+ int width,const char *digits)
+{
+ char buffer[16];
+ char *op;
+ int retval;
+
+ op = &buffer[0];
+ retval = 0;
+
+#ifdef _MIPSREGS32_
+ /*
+ * Hack: to avoid pulling in the helper library that isn't necessarily
+ * compatible with PIC code, force radix to 16, use shifts and masks
+ */
+ do {
+ *op++ = digits[num & 0x0F];
+ retval++;
+ num >>= 4;
+ } while (num != 0);
+#else
+ do {
+ *op++ = digits[num % radix];
+ retval++;
+ num /= radix;
+ } while (num != 0);
+#endif
+
+ if (width && (width > retval)) {
+ width = width - retval;
+ while (width) {
+ *op++ = '0';
+ retval++;
+ width--;
+ }
+ }
+
+ while (op != buffer) {
+ op--;
+ *buf++ = *op;
+ }
+
+ return retval;
+}
+
+/* *********************************************************************
+ * xvsprintf(outbuf,template,arglist)
+ *
+ * Format a string into the output buffer
+ *
+ * Input Parameters:
+ * outbuf - output buffer
+ * template - template string
+ * arglist - parameters
+ *
+ * Return Value:
+ * number of characters copied
+ ********************************************************************* */
+#define isdigit(x) (((x) >= '0') && ((x) <= '9'))
+int xvsprintf(char *outbuf,const char *templat,va_list marker)
+{
+ char *optr;
+ const char *iptr;
+ unsigned char *tmpptr;
+ unsigned int x;
+ unsigned long long lx;
+ int i;
+ long long ll;
+ int leadingzero;
+ int leadingnegsign;
+ int islong;
+ int width;
+ int width2 = 0;
+ int hashash = 0;
+
+ optr = outbuf;
+ iptr = templat;
+
+ while (*iptr) {
+ if (*iptr != '%') {*optr++ = *iptr++; continue;}
+
+ iptr++;
+
+ if (*iptr == '#') { hashash = 1; iptr++; }
+ if (*iptr == '-') {
+ leadingnegsign = 1;
+ iptr++;
+ }
+ else leadingnegsign = 0;
+
+ if (*iptr == '0') leadingzero = 1;
+ else leadingzero = 0;
+
+ width = 0;
+ while (*iptr && isdigit(*iptr)) {
+ width += (*iptr - '0');
+ iptr++;
+ if (isdigit(*iptr)) width *= 10;
+ }
+ if (*iptr == '.') {
+ iptr++;
+ width2 = 0;
+ while (*iptr && isdigit(*iptr)) {
+ width2 += (*iptr - '0');
+ iptr++;
+ if (isdigit(*iptr)) width2 *= 10;
+ }
+ }
+
+ islong = 0;
+ if (*iptr == 'l') { islong++; iptr++; }
+ if (*iptr == 'l') { islong++; iptr++; }
+
+ switch (*iptr) {
+ case 'I':
+ tmpptr = (unsigned char *) va_arg(marker,unsigned char *);
+ optr += __atox(optr,*tmpptr++,10,0,digits);
+ *optr++ = '.';
+ optr += __atox(optr,*tmpptr++,10,0,digits);
+ *optr++ = '.';
+ optr += __atox(optr,*tmpptr++,10,0,digits);
+ *optr++ = '.';
+ optr += __atox(optr,*tmpptr++,10,0,digits);
+ break;
+ case 's':
+ tmpptr = (unsigned char *) va_arg(marker,unsigned char *);
+ if (!tmpptr) tmpptr = (unsigned char *) "(null)";
+ if ((width == 0) & (width2 == 0)) {
+ while (*tmpptr) *optr++ = *tmpptr++;
+ break;
+ }
+ while (width && *tmpptr) {
+ *optr++ = *tmpptr++;
+ width--;
+ }
+ while (width) {
+ *optr++ = ' ';
+ width--;
+ }
+ break;
+ case 'a':
+ tmpptr = (unsigned char *) va_arg(marker,unsigned char *);
+ for (x = 0; x < 5; x++) {
+ optr += __atox(optr,*tmpptr++,16,2,digits);
+ *optr++ = '-';
+ }
+ optr += __atox(optr,*tmpptr++,16,2,digits);
+ break;
+ case 'd':
+ switch (islong) {
+ case 0:
+ case 1:
+ i = va_arg(marker,int);
+ if (i < 0) { *optr++='-'; i = -i;}
+ optr += __atox(optr,i,10,width,digits);
+ break;
+ case 2:
+ ll = va_arg(marker,long long int);
+ if (ll < 0) { *optr++='-'; ll = -ll;}
+ optr += __llatox(optr,ll,10,width,digits);
+ break;
+ }
+ break;
+ case 'u':
+ switch (islong) {
+ case 0:
+ case 1:
+ x = va_arg(marker,unsigned int);
+ optr += __atox(optr,x,10,width,digits);
+ break;
+ case 2:
+ lx = va_arg(marker,unsigned long long);
+ optr += __llatox(optr,lx,10,width,digits);
+ break;
+ }
+ break;
+ case 'X':
+ case 'x':
+ switch (islong) {
+ case 0:
+ case 1:
+ x = va_arg(marker,unsigned int);
+ optr += __atox(optr,x,16,width,
+ (*iptr == 'X') ? digits : ldigits);
+ break;
+ case 2:
+ lx = va_arg(marker,unsigned long long);
+ optr += __llatox(optr,lx,16,width,
+ (*iptr == 'X') ? digits : ldigits);
+ break;
+ }
+ break;
+ case 'p':
+ case 'P':
+#ifdef __long64
+ lx = va_arg(marker,unsigned long long);
+ optr += __llatox(optr,lx,16,16,
+ (*iptr == 'P') ? digits : ldigits);
+#else
+ x = va_arg(marker,unsigned int);
+ optr += __atox(optr,x,16,8,
+ (*iptr == 'P') ? digits : ldigits);
+#endif
+ break;
+ case 'w':
+ x = va_arg(marker,unsigned int);
+ x &= 0x0000FFFF;
+ optr += __atox(optr,x,16,4,digits);
+ break;
+ case 'b':
+ x = va_arg(marker,unsigned int);
+ x &= 0x0000FF;
+ optr += __atox(optr,x,16,2,digits);
+ break;
+ case 'Z':
+ x = va_arg(marker,unsigned int);
+ tmpptr = va_arg(marker,unsigned char *);
+ while (x) {
+ optr += __atox(optr,*tmpptr++,16,2,digits);
+ x--;
+ }
+ break;
+ case 'c':
+ x = va_arg(marker, int);
+ *optr++ = x & 0xff;
+ break;
+
+ default:
+ *optr++ = *iptr;
+ break;
+ }
+ iptr++;
+ }
+
+ *optr = '\0';
+
+ return (optr - outbuf);
+}
+
+
+/* *********************************************************************
+ * xsprintf(buf,template,params..)
+ *
+ * format messages from template into a buffer.
+ *
+ * Input Parameters:
+ * buf - output buffer
+ * template - template string
+ * params... parameters
+ *
+ * Return Value:
+ * number of bytes copied to buffer
+ ********************************************************************* */
+int xsprintf(char *buf,const char *templat,...)
+{
+ va_list marker;
+ int count;
+
+ va_start(marker,templat);
+ count = xvsprintf(buf,templat,marker);
+ va_end(marker);
+
+ return count;
+}
+
+/* *********************************************************************
+ * xprintf(template,...)
+ *
+ * A miniature printf.
+ *
+ * %a - Ethernet address (16 bytes)
+ * %s - unpacked string, null terminated
+ * %x - hex word (machine size)
+ * %w - hex word (16 bits)
+ * %b - hex byte (8 bits)
+ * %Z - buffer (put length first, then buffer address)
+ *
+ * Return value:
+ * number of bytes written
+ ********************************************************************* */
+
+int xprintf(const char *templat,...)
+{
+ va_list marker;
+ int count;
+ char buffer[512];
+
+ va_start(marker,templat);
+ count = xvsprintf(buffer,templat,marker);
+ va_end(marker);
+
+ if (xprinthook) (*xprinthook)(buffer);
+
+ return count;
+}
+
+
+int xvprintf(const char *templat,va_list marker)
+{
+ int count;
+ char buffer[512];
+
+ count = xvsprintf(buffer,templat,marker);
+
+ if (xprinthook) (*xprinthook)(buffer);
+
+ return count;
+}
+
+
+
+
+
+
+
+
diff --git a/cfe/cfe/lib/lib_qsort.c b/cfe/cfe/lib/lib_qsort.c
new file mode 100644
index 0000000..f3c60b8
--- /dev/null
+++ b/cfe/cfe/lib/lib_qsort.c
@@ -0,0 +1,88 @@
+#include "lib_types.h"
+#include "lib_string.h"
+
+#define CHAR_BIT 8
+#define MAXSTACK (sizeof(int) * CHAR_BIT)
+
+static void qsexchange(void *a, void *b, size_t size)
+{
+ size_t i;
+
+ /******************
+ * exchange a,b *
+ ******************/
+
+ for (i = sizeof(int); i <= size; i += sizeof(int)) {
+ int t = *((int *)a);
+ *(((int *)a)++) = *((int *)b);
+ *(((int *)b)++) = t;
+ }
+ for (i = i - sizeof(int) + 1; i <= size; i++) {
+ char t = *((char *)a);
+ *(((char *)a)++) = *((char *)b);
+ *(((char *)b)++) = t;
+ }
+}
+
+void qsort(void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *))
+{
+ void *lbStack[MAXSTACK], *ubStack[MAXSTACK];
+ int sp;
+ unsigned int offset;
+
+ /********************
+ * ANSI-C qsort() *
+ ********************/
+
+ lbStack[0] = (char *)base;
+ ubStack[0] = (char *)base + (nmemb-1)*size;
+ for (sp = 0; sp >= 0; sp--) {
+ char *lb, *ub, *m;
+ char *P, *i, *j;
+
+ lb = lbStack[sp];
+ ub = ubStack[sp];
+
+ while (lb < ub) {
+
+ /* select pivot and exchange with 1st element */
+ offset = (ub - lb) >> 1;
+ P = lb + offset - offset % size;
+ qsexchange (lb, P, size);
+
+ /* partition into two segments */
+ i = lb + size;
+ j = ub;
+ while (1) {
+ while (i < j && compar(lb, i) > 0) i += size;
+ while (j >= i && compar(j, lb) > 0) j -= size;
+ if (i >= j) break;
+ qsexchange (i, j, size);
+ j -= size;
+ i += size;
+ }
+
+ /* pivot belongs in A[j] */
+ qsexchange (lb, j, size);
+ m = j;
+
+ /* keep processing smallest segment, and stack largest */
+ if (m - lb <= ub - m) {
+ if (m + size < ub) {
+ lbStack[sp] = m + size;
+ ubStack[sp++] = ub;
+ }
+ ub = m - size;
+ }
+ else {
+ if (m - size > lb) {
+ lbStack[sp] = lb;
+ ubStack[sp++] = m - size;
+ }
+ lb = m + size;
+ }
+ }
+ }
+}
+
diff --git a/cfe/cfe/lib/lib_queue.c b/cfe/cfe/lib/lib_queue.c
new file mode 100644
index 0000000..0712adf
--- /dev/null
+++ b/cfe/cfe/lib/lib_queue.c
@@ -0,0 +1,219 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Queue Management routines File: lib_queue.c
+ *
+ * Routines to manage doubly-linked queues.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_queue.h"
+
+
+/* *********************************************************************
+ * Q_ENQUEUE(qb,item)
+ *
+ * Add item to a queue
+ *
+ * Input Parameters:
+ * qb - queue block
+ * item - item to add
+ *
+ * Return Value:
+ * Nothing.
+ ********************************************************************* */
+
+void q_enqueue(queue_t *qb,queue_t *item)
+{
+ qb->q_prev->q_next = item;
+ item->q_next = qb;
+ item->q_prev = qb->q_prev;
+ qb->q_prev = item;
+}
+
+
+/* *********************************************************************
+ * Q_DEQUEUE(element)
+ *
+ * Remove an element from the queue
+ *
+ * Input Parameters:
+ * element - element to remove
+ *
+ * Return Value:
+ * Nothing.
+ ********************************************************************* */
+
+void q_dequeue(queue_t *item)
+{
+ item->q_prev->q_next = item->q_next;
+ item->q_next->q_prev = item->q_prev;
+}
+
+
+/* *********************************************************************
+ * Q_DEQNEXT(qb)
+ *
+ * Dequeue next element from the specified queue
+ *
+ * Input Parameters:
+ * qb - queue block
+ *
+ * Return Value:
+ * next element, or NULL
+ ********************************************************************* */
+
+queue_t *q_deqnext(queue_t *qb)
+{
+ if (qb->q_next == qb) {
+ return NULL;
+ }
+
+ qb = qb->q_next;
+
+ qb->q_prev->q_next = qb->q_next;
+ qb->q_next->q_prev = qb->q_prev;
+
+ return qb;
+}
+
+
+/* *********************************************************************
+ * Q_MAP(qb)
+ *
+ * "Map" a queue, calling the specified function for each
+ * element in the queue
+ *
+ * If the function returns nonzero, q_map will terminate.
+ *
+ * Input Parameters:
+ * qb - queue block
+ * fn - function pointer
+ * a,b - parameters for the function
+ *
+ * Return Value:
+ * return value from function, or zero if entire queue
+ * was mapped.
+ ********************************************************************* */
+
+int q_map(queue_t *qb, int (*func)(queue_t *,unsigned int,unsigned int),
+ unsigned int a,unsigned int b)
+{
+ queue_t *qe;
+ queue_t *nextq;
+ int res;
+
+ qe = qb;
+
+ qe = qb->q_next;
+
+ while (qe != qb) {
+ nextq = qe->q_next;
+ if ((res = (*func)(qe,a,b))) return res;
+ qe = nextq;
+ }
+
+ return 0;
+}
+
+
+
+
+
+/* *********************************************************************
+ * Q_COUNT(qb) *
+ * *
+ * Counts the elements on a queue (not interlocked) *
+ * *
+ * Input Parameters: *
+ * qb - queue block *
+ * *
+ * Return Value: *
+ * number of elements *
+ ********************************************************************* */
+int q_count(queue_t *qb)
+{
+ queue_t *qe;
+ int res = 0;
+
+ qe = qb;
+
+ while (qe->q_next != qb) {
+ qe = qe->q_next;
+ res++;
+ }
+
+ return res;
+}
+
+
+
+
+/* *********************************************************************
+ * Q_FIND(qb,item)
+ *
+ * Determines if a particular element is on a queue.
+ *
+ * Input Parameters:
+ * qb - queue block
+ * item - queue element
+ *
+ * Return Value:
+ * 0 - not on queue
+ * >0 - position on queue
+ ********************************************************************* */
+int q_find(queue_t *qb,queue_t *item)
+{
+ queue_t *q;
+ int res = 1;
+
+ q = qb->q_next;
+
+ while (q != item) {
+ if (q == qb) return 0;
+ q = q->q_next;
+ res++;
+ }
+
+ return res;
+}
+
diff --git a/cfe/cfe/lib/lib_string.c b/cfe/cfe/lib/lib_string.c
new file mode 100644
index 0000000..08e9ee7
--- /dev/null
+++ b/cfe/cfe/lib/lib_string.c
@@ -0,0 +1,386 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * String routines File: lib_string.c
+ *
+ * Some standard routines for messing with strings.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+
+#include "lib_types.h"
+#define _LIB_NO_MACROS_
+#include "lib_string.h"
+
+char *lib_strcpy(char *dest,const char *src)
+{
+ char *ptr = dest;
+
+ while (*src) *ptr++ = *src++;
+ *ptr = '\0';
+
+ return dest;
+}
+
+char *lib_strncpy(char *dest,const char *src,size_t cnt)
+{
+ char *ptr = dest;
+
+ while (*src && (cnt > 0)) {
+ *ptr++ = *src++;
+ cnt--;
+ }
+ if (cnt > 0) *ptr = '\0';
+
+ return dest;
+}
+
+
+size_t lib_xstrncpy(char *dest,const char *src,size_t cnt)
+{
+ char *ptr = dest;
+ size_t copied = 0;
+
+ while (*src && (cnt > 1)) {
+ *ptr++ = *src++;
+ cnt--;
+ copied++;
+ }
+ *ptr = '\0';
+
+ return copied;
+}
+
+size_t lib_strlen(const char *str)
+{
+ size_t cnt = 0;
+
+ while (*str) {
+ str++;
+ cnt++;
+ }
+
+ return cnt;
+}
+
+
+int lib_strcmp(const char *dest,const char *src)
+{
+ while (*src && *dest) {
+ if (*dest < *src) return -1;
+ if (*dest > *src) return 1;
+ dest++;
+ src++;
+ }
+
+ if (*dest && !*src) return 1;
+ if (!*dest && *src) return -1;
+ return 0;
+}
+
+/* Foxconn add start by Jenny Zhao, 07/02/2008*/
+int lib_strncmp(const char *dest, const char *src, size_t cnt )
+{
+ while (*src && *dest && cnt) {
+ if (*dest < *src ) return -1;
+ if (*dest > *src) return 1;
+ dest++;
+ src++;
+ cnt--;
+ }
+
+ if (!cnt) return 0;
+ if (*dest && !*src) return 1;
+ if (!*dest && *src) return -1;
+ return 0;
+}
+/* Foxconn add start by Jenny Zhao, 07/02/2008*/
+
+
+int lib_strcmpi(const char *dest,const char *src)
+{
+ char dc,sc;
+
+ while (*src && *dest) {
+ dc = lib_toupper(*dest);
+ sc = lib_toupper(*src);
+ if (dc < sc) return -1;
+ if (dc > sc) return 1;
+ dest++;
+ src++;
+ }
+
+ if (*dest && !*src) return 1;
+ if (!*dest && *src) return -1;
+ return 0;
+}
+
+
+char *lib_strchr(const char *dest,int c)
+{
+ while (*dest) {
+ if (*dest == c) return (char *) dest;
+ dest++;
+ }
+ return NULL;
+}
+
+char *lib_strnchr(const char *dest,int c,size_t cnt)
+{
+ while (*dest && (cnt > 0)) {
+ if (*dest == c) return (char *) dest;
+ dest++;
+ cnt--;
+ }
+ return NULL;
+}
+
+char *lib_strrchr(const char *dest,int c)
+{
+ char *ret = NULL;
+
+ while (*dest) {
+ if (*dest == c) ret = (char *) dest;
+ dest++;
+ }
+
+ return ret;
+}
+
+
+int lib_memcmp(const void *dest,const void *src,size_t cnt)
+{
+ const unsigned char *d;
+ const unsigned char *s;
+
+ d = (const unsigned char *) dest;
+ s = (const unsigned char *) src;
+
+ while (cnt) {
+ if (*d < *s) return -1;
+ if (*d > *s) return 1;
+ d++; s++; cnt--;
+ }
+
+ return 0;
+}
+
+void *lib_memcpy(void *dest,const void *src,size_t cnt)
+{
+ unsigned char *d;
+ const unsigned char *s;
+
+ d = (unsigned char *) dest;
+ s = (const unsigned char *) src;
+
+ while (cnt) {
+ *d++ = *s++;
+ cnt--;
+ }
+
+ return dest;
+}
+
+void *lib_memset(void *dest,int c,size_t cnt)
+{
+ unsigned char *d;
+
+ d = dest;
+
+ while (cnt) {
+ *d++ = (unsigned char) c;
+ cnt--;
+ }
+
+ return d;
+}
+
+char lib_toupper(char c)
+{
+ if ((c >= 'a') && (c <= 'z')) c -= 32;
+ return c;
+}
+
+void lib_strupr(char *str)
+{
+ while (*str) {
+ *str = lib_toupper(*str);
+ str++;
+ }
+}
+
+char *lib_strcat(char *dest,const char *src)
+{
+ char *ptr = dest;
+
+ while (*ptr) ptr++;
+ while (*src) *ptr++ = *src++;
+ *ptr = '\0';
+
+ return dest;
+}
+
+#define isspace(x) (((x) == ' ') || ((x) == '\t'))
+
+char *lib_gettoken(char **ptr)
+{
+ char *p = *ptr;
+ char *ret;
+
+ /* skip white space */
+
+ while (*p && isspace(*p)) p++;
+ ret = p;
+
+ /* check for end of string */
+
+ if (!*p) {
+ *ptr = p;
+ return NULL;
+ }
+
+ /* skip non-whitespace */
+
+ while (*p) {
+ if (isspace(*p)) break;
+
+ /* do quoted strings */
+
+ if (*p == '"') {
+ p++;
+ ret = p;
+ while (*p && (*p != '"')) p++;
+ if (*p == '"') *p = '\0';
+ }
+
+ p++;
+
+ }
+
+ if (*p) {
+ *p++ = '\0';
+ }
+ *ptr = p;
+
+ return ret;
+}
+
+
+int lib_atoi(const char *dest)
+{
+ int x = 0;
+ int digit;
+
+ if ((*dest == '0') && (*(dest+1) == 'x')) {
+ return lib_xtoi(dest+2);
+ }
+
+ while (*dest) {
+ if ((*dest >= '0') && (*dest <= '9')) {
+ digit = *dest - '0';
+ }
+ else {
+ break;
+ }
+ x *= 10;
+ x += digit;
+ dest++;
+ }
+
+ return x;
+}
+
+uint64_t lib_xtoq(const char *dest)
+{
+ uint64_t x = 0;
+ unsigned int digit;
+
+ if ((*dest == '0') && (*(dest+1) == 'x')) dest += 2;
+
+ while (*dest) {
+ if ((*dest >= '0') && (*dest <= '9')) {
+ digit = *dest - '0';
+ }
+ else if ((*dest >= 'A') && (*dest <= 'F')) {
+ digit = 10 + *dest - 'A';
+ }
+ else if ((*dest >= 'a') && (*dest <= 'f')) {
+ digit = 10 + *dest - 'a';
+ }
+ else {
+ break;
+ }
+ x *= 16;
+ x += digit;
+ dest++;
+ }
+
+ return x;
+}
+
+int lib_xtoi(const char *dest)
+{
+ int x = 0;
+ int digit;
+
+ if ((*dest == '0') && (*(dest+1) == 'x')) dest += 2;
+
+ while (*dest) {
+ if ((*dest >= '0') && (*dest <= '9')) {
+ digit = *dest - '0';
+ }
+ else if ((*dest >= 'A') && (*dest <= 'F')) {
+ digit = 10 + *dest - 'A';
+ }
+ else if ((*dest >= 'a') && (*dest <= 'f')) {
+ digit = 10 + *dest - 'a';
+ }
+ else {
+ break;
+ }
+ x *= 16;
+ x += digit;
+ dest++;
+ }
+
+ return x;
+}
diff --git a/cfe/cfe/lib/lib_string2.c b/cfe/cfe/lib/lib_string2.c
new file mode 100644
index 0000000..e42070a
--- /dev/null
+++ b/cfe/cfe/lib/lib_string2.c
@@ -0,0 +1,96 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * More string routines File: lib_string2.c
+ *
+ * More routines to muck with strings; these routines typically
+ * need malloc to operate. This way lib_string.c can be incorporated
+ * into other programs that don't need malloc
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#define _LIB_NO_MACROS_
+#include "lib_string.h"
+
+
+char *lib_strdup(char *str)
+{
+ char *buf;
+
+ buf = KMALLOC(lib_strlen(str)+1,0);
+ if (buf) {
+ lib_strcpy(buf,str);
+ }
+
+ return buf;
+}
+
+void lib_trimleading(char *path)
+{
+ if (*path == '/') {
+ lib_strcpy(path, path+1);
+ }
+
+ return;
+}
+
+void lib_chop_filename(char *str,char **host,char **file)
+{
+ char *p;
+
+ *host = str;
+
+ p = lib_strchr(str,':');
+ if (!p) p = lib_strchr(str,'/');
+
+ if (p) {
+ *p++ = '\0';
+ *file = p;
+ }
+ else {
+ *file = NULL;
+ }
+}
+
+
diff --git a/cfe/cfe/lzma/LzmaDecode.c b/cfe/cfe/lzma/LzmaDecode.c
new file mode 100755
index 0000000..cb83453
--- /dev/null
+++ b/cfe/cfe/lzma/LzmaDecode.c
@@ -0,0 +1,584 @@
+/*
+ LzmaDecode.c
+ LZMA Decoder (optimized for Speed version)
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this Code, expressly permits you to
+ statically or dynamically link your Code (or bind by name) to the
+ interfaces of this file without subjecting your linked Code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_READ_BYTE (*Buffer++)
+
+#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
+ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
+
+#ifdef _LZMA_IN_CB
+
+#define RC_TEST { if (Buffer == BufferLim) \
+ { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
+ BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
+
+#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
+
+#else
+
+#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
+
+#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
+
+#endif
+
+#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+
+#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
+ { UpdateBit0(p); mi <<= 1; A0; } else \
+ { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
+
+#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
+
+#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
+ { int i = numLevels; res = 1; \
+ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
+ res -= (1 << numLevels); }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+ unsigned char prop0;
+ if (size < LZMA_PROPERTIES_SIZE)
+ return LZMA_RESULT_DATA_ERROR;
+ prop0 = propsData[0];
+ if (prop0 >= (9 * 5 * 5))
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+ propsRes->lc = prop0;
+ /*
+ unsigned char remainder = (unsigned char)(prop0 / 9);
+ propsRes->lc = prop0 % 9;
+ propsRes->pb = remainder / 5;
+ propsRes->lp = remainder % 5;
+ */
+ }
+
+ #ifdef _LZMA_OUT_READ
+ {
+ int i;
+ propsRes->DictionarySize = 0;
+ for (i = 0; i < 4; i++)
+ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+ if (propsRes->DictionarySize == 0)
+ propsRes->DictionarySize = 1;
+ }
+ #endif
+ return LZMA_RESULT_OK;
+}
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
+{
+ CProb *p = vs->Probs;
+ SizeT nowPos = 0;
+ Byte previousByte = 0;
+ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+ int lc = vs->Properties.lc;
+
+ #ifdef _LZMA_OUT_READ
+
+ UInt32 Range = vs->Range;
+ UInt32 Code = vs->Code;
+ #ifdef _LZMA_IN_CB
+ const Byte *Buffer = vs->Buffer;
+ const Byte *BufferLim = vs->BufferLim;
+ #else
+ const Byte *Buffer = inStream;
+ const Byte *BufferLim = inStream + inSize;
+ #endif
+ int state = vs->State;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+ UInt32 distanceLimit = vs->DistanceLimit;
+
+ Byte *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->Properties.DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ Byte tempDictionary[4];
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+ if (len == kLzmaStreamWasFinishedId)
+ return LZMA_RESULT_OK;
+
+ if (dictionarySize == 0)
+ {
+ dictionary = tempDictionary;
+ dictionarySize = 1;
+ tempDictionary[0] = vs->TempDictionary[0];
+ }
+
+ if (len == kLzmaNeedInitId)
+ {
+ {
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ UInt32 i;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ rep0 = rep1 = rep2 = rep3 = 1;
+ state = 0;
+ globalPos = 0;
+ distanceLimit = 0;
+ dictionaryPos = 0;
+ dictionary[dictionarySize - 1] = 0;
+ #ifdef _LZMA_IN_CB
+ RC_INIT;
+ #else
+ RC_INIT(inStream, inSize);
+ #endif
+ }
+ len = 0;
+ }
+ while(len != 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+
+ #else /* if !_LZMA_OUT_READ */
+
+ int state = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ int len = 0;
+ const Byte *Buffer;
+ const Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+
+ {
+ UInt32 i;
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ }
+
+ #ifdef _LZMA_IN_CB
+ RC_INIT;
+ #else
+ RC_INIT(inStream, inSize);
+ #endif
+
+ #endif /* _LZMA_OUT_READ */
+
+ while(nowPos < outSize)
+ {
+ CProb *prob;
+ UInt32 bound;
+ int posState = (int)(
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & posStateMask);
+
+ prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ int symbol = 1;
+ UpdateBit0(prob)
+ prob = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state >= kNumLitStates)
+ {
+ int matchByte;
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ #else
+ matchByte = outStream[nowPos - rep0];
+ #endif
+ do
+ {
+ int bit;
+ CProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & 0x100);
+ probLit = prob + 0x100 + bit + symbol;
+ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
+ }
+ while (symbol < 0x100);
+ }
+ while (symbol < 0x100)
+ {
+ CProb *probLit = prob + symbol;
+ RC_GET_BIT(probLit, symbol)
+ }
+ previousByte = (Byte)symbol;
+
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #endif
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRep + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < kNumLitStates ? 0 : 3;
+ prob = p + LenCoder;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG0 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos;
+ #endif
+ UpdateBit0(prob);
+
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit == 0)
+ #else
+ if (nowPos == 0)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ state = state < kNumLitStates ? 9 : 11;
+ #ifdef _LZMA_OUT_READ
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+ #endif
+
+ continue;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ UpdateBit1(prob);
+ prob = p + IsRepG1 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep1;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG2 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep2;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ state = state < kNumLitStates ? 8 : 11;
+ prob = p + RepLenCoder;
+ }
+ {
+ int numBits, offset;
+ CProb *probLen = prob + LenChoice;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ numBits = kLenNumLowBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenChoice2;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ numBits = kLenNumMidBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ numBits = kLenNumHighBits;
+ }
+ }
+ RangeDecoderBitTreeDecode(probLen, numBits, len);
+ len += offset;
+ }
+
+ if (state < 4)
+ {
+ int posSlot;
+ state += kNumLitStates;
+ prob = p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits);
+ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = (2 | ((UInt32)posSlot & 1));
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 <<= numDirectBits;
+ prob = p + SpecPos + rep0 - posSlot - 1;
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ RC_NORMALIZE
+ Range >>= 1;
+ rep0 <<= 1;
+ if (Code >= Range)
+ {
+ Code -= Range;
+ rep0 |= 1;
+ }
+ }
+ while (--numDirectBits != 0);
+ prob = p + Align;
+ rep0 <<= kNumAlignBits;
+ numDirectBits = kNumAlignBits;
+ }
+ {
+ int i = 1;
+ int mi = 1;
+ do
+ {
+ CProb *prob3 = prob + mi;
+ RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
+ i <<= 1;
+ }
+ while(--numDirectBits != 0);
+ }
+ }
+ else
+ rep0 = posSlot;
+ if (++rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = kLzmaStreamWasFinishedId;
+ break;
+ }
+ }
+
+ len += kMatchMinLen;
+ #ifdef _LZMA_OUT_READ
+ if (rep0 > distanceLimit)
+ #else
+ if (rep0 > nowPos)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ #ifdef _LZMA_OUT_READ
+ if (dictionarySize - distanceLimit > (UInt32)len)
+ distanceLimit += len;
+ else
+ distanceLimit = dictionarySize;
+ #endif
+
+ do
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ len--;
+ outStream[nowPos++] = previousByte;
+ }
+ while(len != 0 && nowPos < outSize);
+ }
+ }
+ RC_NORMALIZE;
+
+ #ifdef _LZMA_OUT_READ
+ vs->Range = Range;
+ vs->Code = Code;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = globalPos + (UInt32)nowPos;
+ vs->DistanceLimit = distanceLimit;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->RemainLen = len;
+ vs->TempDictionary[0] = tempDictionary[0];
+ #endif
+
+ #ifdef _LZMA_IN_CB
+ vs->Buffer = Buffer;
+ vs->BufferLim = BufferLim;
+ #else
+ *inSizeProcessed = (SizeT)(Buffer - inStream);
+ #endif
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
diff --git a/cfe/cfe/lzma/LzmaDecode.h b/cfe/cfe/lzma/LzmaDecode.h
new file mode 100755
index 0000000..2870eeb
--- /dev/null
+++ b/cfe/cfe/lzma/LzmaDecode.h
@@ -0,0 +1,113 @@
+/*
+ LzmaDecode.h
+ LZMA Decoder interface
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMADECODE_H
+#define __LZMADECODE_H
+
+#include "LzmaTypes.h"
+
+/* #define _LZMA_IN_CB */
+/* Use callback for input data */
+
+/* #define _LZMA_OUT_READ */
+/* Use read function for output data */
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case */
+
+/* #define _LZMA_LOC_OPT */
+/* Enable local speed optimizations inside code */
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb UInt16
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+#ifdef _LZMA_IN_CB
+typedef struct _ILzmaInCallback
+{
+ int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
+} ILzmaInCallback;
+#endif
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_PROPERTIES_SIZE 5
+
+typedef struct _CLzmaProperties
+{
+ int lc;
+ int lp;
+ int pb;
+ #ifdef _LZMA_OUT_READ
+ UInt32 DictionarySize;
+ #endif
+}CLzmaProperties;
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
+
+#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
+
+#define kLzmaNeedInitId (-2)
+
+typedef struct _CLzmaDecoderState
+{
+ CLzmaProperties Properties;
+ CProb *Probs;
+
+ #ifdef _LZMA_IN_CB
+ const unsigned char *Buffer;
+ const unsigned char *BufferLim;
+ #endif
+
+ #ifdef _LZMA_OUT_READ
+ unsigned char *Dictionary;
+ UInt32 Range;
+ UInt32 Code;
+ UInt32 DictionaryPos;
+ UInt32 GlobalPos;
+ UInt32 DistanceLimit;
+ UInt32 Reps[4];
+ int State;
+ int RemainLen;
+ unsigned char TempDictionary[4];
+ #endif
+} CLzmaDecoderState;
+
+#ifdef _LZMA_OUT_READ
+#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
+#endif
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
+
+#endif
diff --git a/cfe/cfe/lzma/LzmaDecodeSize.c b/cfe/cfe/lzma/LzmaDecodeSize.c
new file mode 100755
index 0000000..a3a5eb9
--- /dev/null
+++ b/cfe/cfe/lzma/LzmaDecodeSize.c
@@ -0,0 +1,712 @@
+/*
+ LzmaDecodeSize.c
+ LZMA Decoder (optimized for Size version)
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+typedef struct _CRangeDecoder
+{
+ const Byte *Buffer;
+ const Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback;
+ int Result;
+ #endif
+ int ExtraBytes;
+} CRangeDecoder;
+
+Byte RangeDecoderReadByte(CRangeDecoder *rd)
+{
+ if (rd->Buffer == rd->BufferLim)
+ {
+ #ifdef _LZMA_IN_CB
+ SizeT size;
+ rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
+ rd->BufferLim = rd->Buffer + size;
+ if (size == 0)
+ #endif
+ {
+ rd->ExtraBytes = 1;
+ return 0xFF;
+ }
+ }
+ return (*rd->Buffer++);
+}
+
+/* #define ReadByte (*rd->Buffer++) */
+#define ReadByte (RangeDecoderReadByte(rd))
+
+void RangeDecoderInit(CRangeDecoder *rd
+ #ifndef _LZMA_IN_CB
+ , const Byte *stream, SizeT bufferSize
+ #endif
+ )
+{
+ int i;
+ #ifdef _LZMA_IN_CB
+ rd->Buffer = rd->BufferLim = 0;
+ #else
+ rd->Buffer = stream;
+ rd->BufferLim = stream + bufferSize;
+ #endif
+ rd->ExtraBytes = 0;
+ rd->Code = 0;
+ rd->Range = (0xFFFFFFFF);
+ for(i = 0; i < 5; i++)
+ rd->Code = (rd->Code << 8) | ReadByte;
+}
+
+#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;
+#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
+#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
+
+UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
+{
+ RC_INIT_VAR
+ UInt32 result = 0;
+ int i;
+ for (i = numTotalBits; i != 0; i--)
+ {
+ /* UInt32 t; */
+ range >>= 1;
+
+ result <<= 1;
+ if (code >= range)
+ {
+ code -= range;
+ result |= 1;
+ }
+ /*
+ t = (code - range) >> 31;
+ t &= 1;
+ code -= range & (t - 1);
+ result = (result + result) | (1 - t);
+ */
+ RC_NORMALIZE
+ }
+ RC_FLUSH_VAR
+ return result;
+}
+
+int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
+{
+ UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
+ if (rd->Code < bound)
+ {
+ rd->Range = bound;
+ *prob += (kBitModelTotal - *prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 0;
+ }
+ else
+ {
+ rd->Range -= bound;
+ rd->Code -= bound;
+ *prob -= (*prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 1;
+ }
+}
+
+#define RC_GET_BIT2(prob, mi, A0, A1) \
+ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
+ if (code < bound) \
+ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
+ else \
+ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
+ RC_NORMALIZE
+
+#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
+
+int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = numLevels; i != 0; i--)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT(prob, mi)
+ #else
+ mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return mi - (1 << numLevels);
+}
+
+int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ int symbol = 0;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = 0; i < numLevels; i++)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
+ #else
+ int bit = RangeDecoderBitDecode(probs + mi, rd);
+ mi = mi + mi + bit;
+ symbol |= (bit << i);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ int bit;
+ int matchBit = (matchByte >> 7) & 1;
+ matchByte <<= 1;
+ #ifdef _LZMA_LOC_OPT
+ {
+ CProb *prob = probs + 0x100 + (matchBit << 8) + symbol;
+ RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
+ }
+ #else
+ bit = RangeDecoderBitDecode(probs + 0x100 + (matchBit << 8) + symbol, rd);
+ symbol = (symbol << 1) | bit;
+ #endif
+ if (matchBit != bit)
+ {
+ while (symbol < 0x100)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ break;
+ }
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
+{
+ if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
+ return RangeDecoderBitTreeDecode(p + LenLow +
+ (posState << kLenNumLowBits), kLenNumLowBits, rd);
+ if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
+ return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
+ (posState << kLenNumMidBits), kLenNumMidBits, rd);
+ return kLenNumLowSymbols + kLenNumMidSymbols +
+ RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
+}
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+ unsigned char prop0;
+ if (size < LZMA_PROPERTIES_SIZE)
+ return LZMA_RESULT_DATA_ERROR;
+ prop0 = propsData[0];
+ if (prop0 >= (9 * 5 * 5))
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+ propsRes->lc = prop0;
+ /*
+ unsigned char remainder = (unsigned char)(prop0 / 9);
+ propsRes->lc = prop0 % 9;
+ propsRes->pb = remainder / 5;
+ propsRes->lp = remainder % 5;
+ */
+ }
+
+ #ifdef _LZMA_OUT_READ
+ {
+ int i;
+ propsRes->DictionarySize = 0;
+ for (i = 0; i < 4; i++)
+ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+ if (propsRes->DictionarySize == 0)
+ propsRes->DictionarySize = 1;
+ }
+ #endif
+ return LZMA_RESULT_OK;
+}
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
+{
+ CProb *p = vs->Probs;
+ SizeT nowPos = 0;
+ Byte previousByte = 0;
+ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+ int lc = vs->Properties.lc;
+ CRangeDecoder rd;
+
+ #ifdef _LZMA_OUT_READ
+
+ int state = vs->State;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+ UInt32 distanceLimit = vs->DistanceLimit;
+
+ Byte *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->Properties.DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ Byte tempDictionary[4];
+
+ rd.Range = vs->Range;
+ rd.Code = vs->Code;
+ #ifdef _LZMA_IN_CB
+ rd.InCallback = InCallback;
+ rd.Buffer = vs->Buffer;
+ rd.BufferLim = vs->BufferLim;
+ #else
+ rd.Buffer = inStream;
+ rd.BufferLim = inStream + inSize;
+ #endif
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+ if (len == kLzmaStreamWasFinishedId)
+ return LZMA_RESULT_OK;
+
+ if (dictionarySize == 0)
+ {
+ dictionary = tempDictionary;
+ dictionarySize = 1;
+ tempDictionary[0] = vs->TempDictionary[0];
+ }
+
+ if (len == kLzmaNeedInitId)
+ {
+ {
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ UInt32 i;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ rep0 = rep1 = rep2 = rep3 = 1;
+ state = 0;
+ globalPos = 0;
+ distanceLimit = 0;
+ dictionaryPos = 0;
+ dictionary[dictionarySize - 1] = 0;
+ RangeDecoderInit(&rd
+ #ifndef _LZMA_IN_CB
+ , inStream, inSize
+ #endif
+ );
+ #ifdef _LZMA_IN_CB
+ if (rd.Result != LZMA_RESULT_OK)
+ return rd.Result;
+ #endif
+ if (rd.ExtraBytes != 0)
+ return LZMA_RESULT_DATA_ERROR;
+ }
+ len = 0;
+ }
+ while(len != 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+
+ #ifdef _LZMA_IN_CB
+ rd.Result = LZMA_RESULT_OK;
+ #endif
+ rd.ExtraBytes = 0;
+
+ #else /* if !_LZMA_OUT_READ */
+
+ int state = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ int len = 0;
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+
+ {
+ UInt32 i;
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ }
+
+ #ifdef _LZMA_IN_CB
+ rd.InCallback = InCallback;
+ #endif
+ RangeDecoderInit(&rd
+ #ifndef _LZMA_IN_CB
+ , inStream, inSize
+ #endif
+ );
+
+ #ifdef _LZMA_IN_CB
+ if (rd.Result != LZMA_RESULT_OK)
+ return rd.Result;
+ #endif
+ if (rd.ExtraBytes != 0)
+ return LZMA_RESULT_DATA_ERROR;
+
+ #endif /* _LZMA_OUT_READ */
+
+
+ while(nowPos < outSize)
+ {
+ int posState = (int)(
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & posStateMask);
+ #ifdef _LZMA_IN_CB
+ if (rd.Result != LZMA_RESULT_OK)
+ return rd.Result;
+ #endif
+ if (rd.ExtraBytes != 0)
+ return LZMA_RESULT_DATA_ERROR;
+ if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ CProb *probs = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state >= kNumLitStates)
+ {
+ Byte matchByte;
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ #else
+ matchByte = outStream[nowPos - rep0];
+ #endif
+ previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
+ }
+ else
+ previousByte = LzmaLiteralDecode(probs, &rd);
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #endif
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ }
+ else
+ {
+ if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
+ {
+ if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
+ {
+ if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos;
+ #endif
+
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit == 0)
+ #else
+ if (nowPos == 0)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ state = state < 7 ? 9 : 11;
+ #ifdef _LZMA_OUT_READ
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+ #endif
+ continue;
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
+ distance = rep1;
+ else
+ {
+ if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
+ distance = rep2;
+ else
+ {
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
+ state = state < 7 ? 8 : 11;
+ }
+ else
+ {
+ int posSlot;
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < 7 ? 7 : 10;
+ len = LzmaLenDecode(p + LenCoder, &rd, posState);
+ posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits), kNumPosSlotBits, &rd);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 += RangeDecoderReverseBitTreeDecode(
+ p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
+ }
+ else
+ {
+ rep0 += RangeDecoderDecodeDirectBits(&rd,
+ numDirectBits - kNumAlignBits) << kNumAlignBits;
+ rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
+ }
+ }
+ else
+ rep0 = posSlot;
+ if (++rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = kLzmaStreamWasFinishedId;
+ break;
+ }
+ }
+
+ len += kMatchMinLen;
+ #ifdef _LZMA_OUT_READ
+ if (rep0 > distanceLimit)
+ #else
+ if (rep0 > nowPos)
+ #endif
+ return LZMA_RESULT_DATA_ERROR;
+
+ #ifdef _LZMA_OUT_READ
+ if (dictionarySize - distanceLimit > (UInt32)len)
+ distanceLimit += len;
+ else
+ distanceLimit = dictionarySize;
+ #endif
+
+ do
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ len--;
+ outStream[nowPos++] = previousByte;
+ }
+ while(len != 0 && nowPos < outSize);
+ }
+ }
+
+
+ #ifdef _LZMA_OUT_READ
+ vs->Range = rd.Range;
+ vs->Code = rd.Code;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = globalPos + (UInt32)nowPos;
+ vs->DistanceLimit = distanceLimit;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->RemainLen = len;
+ vs->TempDictionary[0] = tempDictionary[0];
+ #endif
+
+ #ifdef _LZMA_IN_CB
+ vs->Buffer = rd.Buffer;
+ vs->BufferLim = rd.BufferLim;
+ #else
+ *inSizeProcessed = (SizeT)(rd.Buffer - inStream);
+ #endif
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
diff --git a/cfe/cfe/lzma/LzmaStateDecode.c b/cfe/cfe/lzma/LzmaStateDecode.c
new file mode 100755
index 0000000..e50f88b
--- /dev/null
+++ b/cfe/cfe/lzma/LzmaStateDecode.c
@@ -0,0 +1,521 @@
+/*
+ LzmaStateDecode.c
+ LZMA Decoder (State version)
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this Code, expressly permits you to
+ statically or dynamically link your Code (or bind by name) to the
+ interfaces of this file without subjecting your linked Code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaStateDecode.h"
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_READ_BYTE (*Buffer++)
+
+#define RC_INIT Code = 0; Range = 0xFFFFFFFF; \
+ { int i; for(i = 0; i < 5; i++) { Code = (Code << 8) | RC_READ_BYTE; }}
+
+#define RC_NORMALIZE if (Range < kTopValue) { Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+
+#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
+ { UpdateBit0(p); mi <<= 1; A0; } else \
+ { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
+
+#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
+
+#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
+ { int i = numLevels; res = 1; \
+ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
+ res -= (1 << numLevels); }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+/* kRequiredInBufferSize = number of required input bytes for worst case:
+ longest match with longest distance.
+ kLzmaInBufferSize must be larger than kRequiredInBufferSize
+ 23 bits = 2 (match select) + 10 (len) + 6 (distance) + 4(align) + 1 (RC_NORMALIZE)
+*/
+
+#define kRequiredInBufferSize ((23 * (kNumBitModelTotalBits - kNumMoveBits + 1) + 26 + 9) / 8)
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+ unsigned char prop0;
+ if (size < LZMA_PROPERTIES_SIZE)
+ return LZMA_RESULT_DATA_ERROR;
+ prop0 = propsData[0];
+ if (prop0 >= (9 * 5 * 5))
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+ propsRes->lc = prop0;
+ /*
+ unsigned char remainder = (unsigned char)(prop0 / 9);
+ propsRes->lc = prop0 % 9;
+ propsRes->pb = remainder / 5;
+ propsRes->lp = remainder % 5;
+ */
+ }
+
+ {
+ int i;
+ propsRes->DictionarySize = 0;
+ for (i = 0; i < 4; i++)
+ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+ if (propsRes->DictionarySize == 0)
+ propsRes->DictionarySize = 1;
+ return LZMA_RESULT_OK;
+ }
+}
+
+int LzmaDecode(
+ CLzmaDecoderState *vs,
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed,
+ int finishDecoding)
+{
+ UInt32 Range = vs->Range;
+ UInt32 Code = vs->Code;
+
+ unsigned char *Buffer = vs->Buffer;
+ int BufferSize = vs->BufferSize; /* don't change it to unsigned int */
+ CProb *p = vs->Probs;
+
+ int state = vs->State;
+ unsigned char previousByte;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ SizeT nowPos = 0;
+ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+ int lc = vs->Properties.lc;
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+ UInt32 distanceLimit = vs->DistanceLimit;
+
+ unsigned char *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->Properties.DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ unsigned char tempDictionary[4];
+
+ (*inSizeProcessed) = 0;
+ (*outSizeProcessed) = 0;
+ if (len == kLzmaStreamWasFinishedId)
+ return LZMA_RESULT_OK;
+
+ if (dictionarySize == 0)
+ {
+ dictionary = tempDictionary;
+ dictionarySize = 1;
+ tempDictionary[0] = vs->TempDictionary[0];
+ }
+
+ if (len == kLzmaNeedInitId)
+ {
+ while (inSize > 0 && BufferSize < kLzmaInBufferSize)
+ {
+ Buffer[BufferSize++] = *inStream++;
+ (*inSizeProcessed)++;
+ inSize--;
+ }
+ if (BufferSize < 5)
+ {
+ vs->BufferSize = BufferSize;
+ return finishDecoding ? LZMA_RESULT_DATA_ERROR : LZMA_RESULT_OK;
+ }
+ {
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ UInt32 i;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ rep0 = rep1 = rep2 = rep3 = 1;
+ state = 0;
+ globalPos = 0;
+ distanceLimit = 0;
+ dictionaryPos = 0;
+ dictionary[dictionarySize - 1] = 0;
+ RC_INIT;
+ }
+ len = 0;
+ }
+ while(len != 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+
+ while(1)
+ {
+ int bufferPos = (int)(Buffer - vs->Buffer);
+ if (BufferSize - bufferPos < kRequiredInBufferSize)
+ {
+ int i;
+ BufferSize -= bufferPos;
+ if (BufferSize < 0)
+ return LZMA_RESULT_DATA_ERROR;
+ for (i = 0; i < BufferSize; i++)
+ vs->Buffer[i] = Buffer[i];
+ Buffer = vs->Buffer;
+ while (inSize > 0 && BufferSize < kLzmaInBufferSize)
+ {
+ Buffer[BufferSize++] = *inStream++;
+ (*inSizeProcessed)++;
+ inSize--;
+ }
+ if (BufferSize < kRequiredInBufferSize && !finishDecoding)
+ break;
+ }
+ if (nowPos >= outSize)
+ break;
+ {
+ CProb *prob;
+ UInt32 bound;
+ int posState = (int)((nowPos + globalPos) & posStateMask);
+
+ prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ int symbol = 1;
+ UpdateBit0(prob)
+ prob = p + Literal + (LZMA_LIT_SIZE *
+ ((((nowPos + globalPos)& literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state >= kNumLitStates)
+ {
+ int matchByte;
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ do
+ {
+ int bit;
+ CProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & 0x100);
+ probLit = prob + 0x100 + bit + symbol;
+ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
+ }
+ while (symbol < 0x100);
+ }
+ while (symbol < 0x100)
+ {
+ CProb *probLit = prob + symbol;
+ RC_GET_BIT(probLit, symbol)
+ }
+ previousByte = (unsigned char)symbol;
+
+ outStream[nowPos++] = previousByte;
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRep + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < kNumLitStates ? 0 : 3;
+ prob = p + LenCoder;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG0 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ UInt32 pos;
+ UpdateBit0(prob);
+ if (distanceLimit == 0)
+ return LZMA_RESULT_DATA_ERROR;
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+ state = state < kNumLitStates ? 9 : 11;
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ outStream[nowPos++] = previousByte;
+ continue;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ UpdateBit1(prob);
+ prob = p + IsRepG1 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep1;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG2 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep2;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ state = state < kNumLitStates ? 8 : 11;
+ prob = p + RepLenCoder;
+ }
+ {
+ int numBits, offset;
+ CProb *probLen = prob + LenChoice;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ numBits = kLenNumLowBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenChoice2;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ numBits = kLenNumMidBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ numBits = kLenNumHighBits;
+ }
+ }
+ RangeDecoderBitTreeDecode(probLen, numBits, len);
+ len += offset;
+ }
+
+ if (state < 4)
+ {
+ int posSlot;
+ state += kNumLitStates;
+ prob = p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits);
+ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = (2 | ((UInt32)posSlot & 1));
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 <<= numDirectBits;
+ prob = p + SpecPos + rep0 - posSlot - 1;
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ RC_NORMALIZE
+ Range >>= 1;
+ rep0 <<= 1;
+ if (Code >= Range)
+ {
+ Code -= Range;
+ rep0 |= 1;
+ }
+ }
+ while (--numDirectBits != 0);
+ prob = p + Align;
+ rep0 <<= kNumAlignBits;
+ numDirectBits = kNumAlignBits;
+ }
+ {
+ int i = 1;
+ int mi = 1;
+ do
+ {
+ CProb *prob3 = prob + mi;
+ RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
+ i <<= 1;
+ }
+ while(--numDirectBits != 0);
+ }
+ }
+ else
+ rep0 = posSlot;
+ if (++rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = kLzmaStreamWasFinishedId;
+ break;
+ }
+ }
+
+ len += kMatchMinLen;
+ if (rep0 > distanceLimit)
+ return LZMA_RESULT_DATA_ERROR;
+ if (dictionarySize - distanceLimit > (UInt32)len)
+ distanceLimit += len;
+ else
+ distanceLimit = dictionarySize;
+
+ do
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ outStream[nowPos++] = previousByte;
+ }
+ while(len != 0 && nowPos < outSize);
+ }
+ }
+ }
+ RC_NORMALIZE;
+
+ BufferSize -= (int)(Buffer - vs->Buffer);
+ if (BufferSize < 0)
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ int i;
+ for (i = 0; i < BufferSize; i++)
+ vs->Buffer[i] = Buffer[i];
+ }
+ vs->BufferSize = BufferSize;
+ vs->Range = Range;
+ vs->Code = Code;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = (UInt32)(globalPos + nowPos);
+ vs->DistanceLimit = distanceLimit;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->RemainLen = len;
+ vs->TempDictionary[0] = tempDictionary[0];
+
+ (*outSizeProcessed) = nowPos;
+ return LZMA_RESULT_OK;
+}
diff --git a/cfe/cfe/lzma/LzmaStateDecode.h b/cfe/cfe/lzma/LzmaStateDecode.h
new file mode 100755
index 0000000..26490d6
--- /dev/null
+++ b/cfe/cfe/lzma/LzmaStateDecode.h
@@ -0,0 +1,96 @@
+/*
+ LzmaStateDecode.h
+ LZMA Decoder interface (State version)
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMASTATEDECODE_H
+#define __LZMASTATEDECODE_H
+
+#include "LzmaTypes.h"
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case */
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb UInt16
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_PROPERTIES_SIZE 5
+
+typedef struct _CLzmaProperties
+{
+ int lc;
+ int lp;
+ int pb;
+ UInt32 DictionarySize;
+}CLzmaProperties;
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
+
+#define LzmaGetNumProbs(lzmaProps) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((lzmaProps)->lc + (lzmaProps)->lp)))
+
+#define kLzmaInBufferSize 64 /* don't change it. it must be larger than kRequiredInBufferSize */
+
+#define kLzmaNeedInitId (-2)
+
+typedef struct _CLzmaDecoderState
+{
+ CLzmaProperties Properties;
+ CProb *Probs;
+ unsigned char *Dictionary;
+
+ unsigned char Buffer[kLzmaInBufferSize];
+ int BufferSize;
+
+ UInt32 Range;
+ UInt32 Code;
+ UInt32 DictionaryPos;
+ UInt32 GlobalPos;
+ UInt32 DistanceLimit;
+ UInt32 Reps[4];
+ int State;
+ int RemainLen; /* -2: decoder needs internal initialization
+ -1: stream was finished,
+ 0: ok
+ > 0: need to write RemainLen bytes as match Reps[0],
+ */
+ unsigned char TempDictionary[4]; /* it's required when DictionarySize = 0 */
+} CLzmaDecoderState;
+
+#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; (vs)->BufferSize = 0; }
+
+/* LzmaDecode: decoding from input stream to output stream.
+ If finishDecoding != 0, then there are no more bytes in input stream
+ after inStream[inSize - 1]. */
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed,
+ int finishDecoding);
+
+#endif
diff --git a/cfe/cfe/lzma/LzmaStateTest.c b/cfe/cfe/lzma/LzmaStateTest.c
new file mode 100755
index 0000000..5df4e43
--- /dev/null
+++ b/cfe/cfe/lzma/LzmaStateTest.c
@@ -0,0 +1,195 @@
+/*
+LzmaStateTest.c
+Test application for LZMA Decoder (State version)
+
+This file written and distributed to public domain by Igor Pavlov.
+This file is part of LZMA SDK 4.26 (2005-08-02)
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "LzmaStateDecode.h"
+
+const char *kCantReadMessage = "Can not read input file";
+const char *kCantWriteMessage = "Can not write output file";
+const char *kCantAllocateMessage = "Can not allocate memory";
+
+#define kInBufferSize (1 << 15)
+#define kOutBufferSize (1 << 15)
+
+unsigned char g_InBuffer[kInBufferSize];
+unsigned char g_OutBuffer[kOutBufferSize];
+
+size_t MyReadFile(FILE *file, void *data, size_t size)
+ { return fread(data, 1, size, file); }
+
+int MyReadFileAndCheck(FILE *file, void *data, size_t size)
+ { return (MyReadFile(file, data, size) == size); }
+
+int PrintError(char *buffer, const char *message)
+{
+ sprintf(buffer + strlen(buffer), "\nError: ");
+ sprintf(buffer + strlen(buffer), message);
+ return 1;
+}
+
+int main3(FILE *inFile, FILE *outFile, char *rs)
+{
+ /* We use two 32-bit integers to construct 64-bit integer for file size.
+ You can remove outSizeHigh, if you don't need >= 4GB supporting,
+ or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
+ UInt32 outSize = 0;
+ UInt32 outSizeHigh = 0;
+
+ int waitEOS = 1;
+ /* waitEOS = 1, if there is no uncompressed size in headers,
+ so decoder will wait EOS (End of Stream Marker) in compressed stream */
+
+ int i;
+ int res = 0;
+ CLzmaDecoderState state; /* it's about 140 bytes structure, if int is 32-bit */
+ unsigned char properties[LZMA_PROPERTIES_SIZE];
+ SizeT inAvail = 0;
+ unsigned char *inBuffer = 0;
+
+ if (sizeof(UInt32) < 4)
+ return PrintError(rs, "LZMA decoder needs correct UInt32");
+
+ /* Read LZMA properties for compressed stream */
+
+ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties)))
+ return PrintError(rs, kCantReadMessage);
+
+ /* Read uncompressed size */
+
+ for (i = 0; i < 8; i++)
+ {
+ unsigned char b;
+ if (!MyReadFileAndCheck(inFile, &b, 1))
+ return PrintError(rs, kCantReadMessage);
+ if (b != 0xFF)
+ waitEOS = 0;
+ if (i < 4)
+ outSize += (UInt32)(b) << (i * 8);
+ else
+ outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
+ }
+
+ /* Decode LZMA properties and allocate memory */
+
+ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
+ return PrintError(rs, "Incorrect stream properties");
+ state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+ if (state.Probs == 0)
+ return PrintError(rs, kCantAllocateMessage);
+
+ if (state.Properties.DictionarySize == 0)
+ state.Dictionary = 0;
+ else
+ {
+ state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
+ if (state.Dictionary == 0)
+ {
+ free(state.Probs);
+ return PrintError(rs, kCantAllocateMessage);
+ }
+ }
+
+ /* Decompress */
+
+ LzmaDecoderInit(&state);
+
+ do
+ {
+ SizeT inProcessed, outProcessed;
+ int finishDecoding;
+ UInt32 outAvail = kOutBufferSize;
+ if (!waitEOS && outSizeHigh == 0 && outAvail > outSize)
+ outAvail = outSize;
+ if (inAvail == 0)
+ {
+ inAvail = (SizeT)MyReadFile(inFile, g_InBuffer, kInBufferSize);
+ inBuffer = g_InBuffer;
+ }
+ finishDecoding = (inAvail == 0);
+ res = LzmaDecode(&state,
+ inBuffer, inAvail, &inProcessed,
+ g_OutBuffer, outAvail, &outProcessed,
+ finishDecoding);
+ if (res != 0)
+ {
+ sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
+ res = 1;
+ break;
+ }
+ inAvail -= inProcessed;
+ inBuffer += inProcessed;
+
+ if (outFile != 0)
+ if (fwrite(g_OutBuffer, 1, outProcessed, outFile) != outProcessed)
+ {
+ PrintError(rs, kCantWriteMessage);
+ res = 1;
+ break;
+ }
+
+ if (outSize < outProcessed)
+ outSizeHigh--;
+ outSize -= (UInt32)outProcessed;
+ outSize &= 0xFFFFFFFF;
+
+ if (outProcessed == 0 && finishDecoding)
+ {
+ if (!waitEOS && (outSize != 0 || outSizeHigh != 0))
+ res = 1;
+ break;
+ }
+ }
+ while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS);
+
+ free(state.Dictionary);
+ free(state.Probs);
+ return res;
+}
+
+int main2(int numArgs, const char *args[], char *rs)
+{
+ FILE *inFile = 0;
+ FILE *outFile = 0;
+ int res;
+
+ sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-02\n");
+ if (numArgs < 2 || numArgs > 3)
+ {
+ sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n");
+ return 1;
+ }
+
+ inFile = fopen(args[1], "rb");
+ if (inFile == 0)
+ return PrintError(rs, "Can not open input file");
+
+ if (numArgs > 2)
+ {
+ outFile = fopen(args[2], "wb+");
+ if (outFile == 0)
+ return PrintError(rs, "Can not open output file");
+ }
+
+ res = main3(inFile, outFile, rs);
+
+ if (outFile != 0)
+ fclose(outFile);
+ fclose(inFile);
+ return res;
+}
+
+int main(int numArgs, const char *args[])
+{
+ char rs[800] = { 0 };
+ int res = main2(numArgs, args, rs);
+ printf(rs);
+ return res;
+}
diff --git a/cfe/cfe/lzma/LzmaTest.c b/cfe/cfe/lzma/LzmaTest.c
new file mode 100755
index 0000000..f95a753
--- /dev/null
+++ b/cfe/cfe/lzma/LzmaTest.c
@@ -0,0 +1,342 @@
+/*
+LzmaTest.c
+Test application for LZMA Decoder
+
+This file written and distributed to public domain by Igor Pavlov.
+This file is part of LZMA SDK 4.26 (2005-08-05)
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "LzmaDecode.h"
+
+const char *kCantReadMessage = "Can not read input file";
+const char *kCantWriteMessage = "Can not write output file";
+const char *kCantAllocateMessage = "Can not allocate memory";
+
+size_t MyReadFile(FILE *file, void *data, size_t size)
+{
+ if (size == 0)
+ return 0;
+ return fread(data, 1, size, file);
+}
+
+int MyReadFileAndCheck(FILE *file, void *data, size_t size)
+ { return (MyReadFile(file, data, size) == size);}
+
+size_t MyWriteFile(FILE *file, const void *data, size_t size)
+{
+ if (size == 0)
+ return 0;
+ return fwrite(data, 1, size, file);
+}
+
+int MyWriteFileAndCheck(FILE *file, const void *data, size_t size)
+ { return (MyWriteFile(file, data, size) == size); }
+
+#ifdef _LZMA_IN_CB
+#define kInBufferSize (1 << 15)
+typedef struct _CBuffer
+{
+ ILzmaInCallback InCallback;
+ FILE *File;
+ unsigned char Buffer[kInBufferSize];
+} CBuffer;
+
+int LzmaReadCompressed(void *object, const unsigned char **buffer, SizeT *size)
+{
+ CBuffer *b = (CBuffer *)object;
+ *buffer = b->Buffer;
+ *size = (SizeT)MyReadFile(b->File, b->Buffer, kInBufferSize);
+ return LZMA_RESULT_OK;
+}
+CBuffer g_InBuffer;
+
+#endif
+
+#ifdef _LZMA_OUT_READ
+#define kOutBufferSize (1 << 15)
+unsigned char g_OutBuffer[kOutBufferSize];
+#endif
+
+int PrintError(char *buffer, const char *message)
+{
+ sprintf(buffer + strlen(buffer), "\nError: ");
+ sprintf(buffer + strlen(buffer), message);
+ return 1;
+}
+
+int main3(FILE *inFile, FILE *outFile, char *rs)
+{
+ /* We use two 32-bit integers to construct 64-bit integer for file size.
+ You can remove outSizeHigh, if you don't need >= 4GB supporting,
+ or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
+ UInt32 outSize = 0;
+ UInt32 outSizeHigh = 0;
+ #ifndef _LZMA_OUT_READ
+ SizeT outSizeFull;
+ unsigned char *outStream;
+ #endif
+
+ int waitEOS = 1;
+ /* waitEOS = 1, if there is no uncompressed size in headers,
+ so decoder will wait EOS (End of Stream Marker) in compressed stream */
+
+ #ifndef _LZMA_IN_CB
+ SizeT compressedSize;
+ unsigned char *inStream;
+ #endif
+
+ CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
+ unsigned char properties[LZMA_PROPERTIES_SIZE];
+
+ int res;
+
+ #ifdef _LZMA_IN_CB
+ g_InBuffer.File = inFile;
+ #endif
+
+ if (sizeof(UInt32) < 4)
+ return PrintError(rs, "LZMA decoder needs correct UInt32");
+
+ #ifndef _LZMA_IN_CB
+ {
+ long length;
+ fseek(inFile, 0, SEEK_END);
+ length = ftell(inFile);
+ fseek(inFile, 0, SEEK_SET);
+ if ((long)(SizeT)length != length)
+ return PrintError(rs, "Too big compressed stream");
+ compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8));
+ }
+ #endif
+
+ /* Read LZMA properties for compressed stream */
+
+ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties)))
+ return PrintError(rs, kCantReadMessage);
+
+ /* Read uncompressed size */
+
+ {
+ int i;
+ for (i = 0; i < 8; i++)
+ {
+ unsigned char b;
+ if (!MyReadFileAndCheck(inFile, &b, 1))
+ return PrintError(rs, kCantReadMessage);
+ if (b != 0xFF)
+ waitEOS = 0;
+ if (i < 4)
+ outSize += (UInt32)(b) << (i * 8);
+ else
+ outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
+ }
+
+ #ifndef _LZMA_OUT_READ
+ if (waitEOS)
+ return PrintError(rs, "Stream with EOS marker is not supported");
+ outSizeFull = (SizeT)outSize;
+ if (sizeof(SizeT) >= 8)
+ outSizeFull |= (((SizeT)outSizeHigh << 16) << 16);
+ else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize)
+ return PrintError(rs, "Too big uncompressed stream");
+ #endif
+ }
+
+ /* Decode LZMA properties and allocate memory */
+
+ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
+ return PrintError(rs, "Incorrect stream properties");
+ state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+
+ #ifdef _LZMA_OUT_READ
+ if (state.Properties.DictionarySize == 0)
+ state.Dictionary = 0;
+ else
+ state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
+ #else
+ if (outSizeFull == 0)
+ outStream = 0;
+ else
+ outStream = (unsigned char *)malloc(outSizeFull);
+ #endif
+
+ #ifndef _LZMA_IN_CB
+ if (compressedSize == 0)
+ inStream = 0;
+ else
+ inStream = (unsigned char *)malloc(compressedSize);
+ #endif
+
+ if (state.Probs == 0
+ #ifdef _LZMA_OUT_READ
+ || (state.Dictionary == 0 && state.Properties.DictionarySize != 0)
+ #else
+ || (outStream == 0 && outSizeFull != 0)
+ #endif
+ #ifndef _LZMA_IN_CB
+ || (inStream == 0 && compressedSize != 0)
+ #endif
+ )
+ {
+ free(state.Probs);
+ #ifdef _LZMA_OUT_READ
+ free(state.Dictionary);
+ #else
+ free(outStream);
+ #endif
+ #ifndef _LZMA_IN_CB
+ free(inStream);
+ #endif
+ return PrintError(rs, kCantAllocateMessage);
+ }
+
+ /* Decompress */
+
+ #ifdef _LZMA_IN_CB
+ g_InBuffer.InCallback.Read = LzmaReadCompressed;
+ #else
+ if (!MyReadFileAndCheck(inFile, inStream, compressedSize))
+ return PrintError(rs, kCantReadMessage);
+ #endif
+
+ #ifdef _LZMA_OUT_READ
+ {
+ #ifndef _LZMA_IN_CB
+ SizeT inAvail = compressedSize;
+ const unsigned char *inBuffer = inStream;
+ #endif
+ LzmaDecoderInit(&state);
+ do
+ {
+ #ifndef _LZMA_IN_CB
+ SizeT inProcessed;
+ #endif
+ SizeT outProcessed;
+ SizeT outAvail = kOutBufferSize;
+ if (!waitEOS && outSizeHigh == 0 && outAvail > outSize)
+ outAvail = (SizeT)outSize;
+ res = LzmaDecode(&state,
+ #ifdef _LZMA_IN_CB
+ &g_InBuffer.InCallback,
+ #else
+ inBuffer, inAvail, &inProcessed,
+ #endif
+ g_OutBuffer, outAvail, &outProcessed);
+ if (res != 0)
+ {
+ sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
+ res = 1;
+ break;
+ }
+ #ifndef _LZMA_IN_CB
+ inAvail -= inProcessed;
+ inBuffer += inProcessed;
+ #endif
+
+ if (outFile != 0)
+ if (!MyWriteFileAndCheck(outFile, g_OutBuffer, (size_t)outProcessed))
+ {
+ PrintError(rs, kCantWriteMessage);
+ res = 1;
+ break;
+ }
+
+ if (outSize < outProcessed)
+ outSizeHigh--;
+ outSize -= (UInt32)outProcessed;
+ outSize &= 0xFFFFFFFF;
+
+ if (outProcessed == 0)
+ {
+ if (!waitEOS && (outSize != 0 || outSizeHigh != 0))
+ res = 1;
+ break;
+ }
+ }
+ while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS);
+ }
+
+ #else
+ {
+ #ifndef _LZMA_IN_CB
+ SizeT inProcessed;
+ #endif
+ SizeT outProcessed;
+ res = LzmaDecode(&state,
+ #ifdef _LZMA_IN_CB
+ &g_InBuffer.InCallback,
+ #else
+ inStream, compressedSize, &inProcessed,
+ #endif
+ outStream, outSizeFull, &outProcessed);
+ if (res != 0)
+ {
+ sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
+ res = 1;
+ }
+ else if (outFile != 0)
+ {
+ if (!MyWriteFileAndCheck(outFile, outStream, (size_t)outProcessed))
+ {
+ PrintError(rs, kCantWriteMessage);
+ res = 1;
+ }
+ }
+ }
+ #endif
+
+ free(state.Probs);
+ #ifdef _LZMA_OUT_READ
+ free(state.Dictionary);
+ #else
+ free(outStream);
+ #endif
+ #ifndef _LZMA_IN_CB
+ free(inStream);
+ #endif
+ return res;
+}
+
+int main2(int numArgs, const char *args[], char *rs)
+{
+ FILE *inFile = 0;
+ FILE *outFile = 0;
+ int res;
+
+ sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-05\n");
+ if (numArgs < 2 || numArgs > 3)
+ {
+ sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n");
+ return 1;
+ }
+
+ inFile = fopen(args[1], "rb");
+ if (inFile == 0)
+ return PrintError(rs, "Can not open input file");
+
+ if (numArgs > 2)
+ {
+ outFile = fopen(args[2], "wb+");
+ if (outFile == 0)
+ return PrintError(rs, "Can not open output file");
+ }
+
+ res = main3(inFile, outFile, rs);
+
+ if (outFile != 0)
+ fclose(outFile);
+ fclose(inFile);
+ return res;
+}
+
+int main(int numArgs, const char *args[])
+{
+ char rs[800] = { 0 };
+ int res = main2(numArgs, args, rs);
+ printf(rs);
+ return res;
+}
diff --git a/cfe/cfe/lzma/LzmaTypes.h b/cfe/cfe/lzma/LzmaTypes.h
new file mode 100755
index 0000000..288c5e4
--- /dev/null
+++ b/cfe/cfe/lzma/LzmaTypes.h
@@ -0,0 +1,45 @@
+/*
+LzmaTypes.h
+
+Types for LZMA Decoder
+
+This file written and distributed to public domain by Igor Pavlov.
+This file is part of LZMA SDK 4.40 (2006-05-01)
+*/
+
+#ifndef __LZMATYPES_H
+#define __LZMATYPES_H
+
+#ifndef _7ZIP_BYTE_DEFINED
+#define _7ZIP_BYTE_DEFINED
+typedef unsigned char Byte;
+#endif
+
+#ifndef _7ZIP_UINT16_DEFINED
+#define _7ZIP_UINT16_DEFINED
+typedef unsigned short UInt16;
+#endif
+
+#ifndef _7ZIP_UINT32_DEFINED
+#define _7ZIP_UINT32_DEFINED
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef unsigned long UInt32;
+#else
+typedef unsigned int UInt32;
+#endif
+#endif
+
+/* #define _LZMA_SYSTEM_SIZE_T */
+/* Use system's size_t. You can use it to enable 64-bit sizes supporting */
+
+#ifndef _7ZIP_SIZET_DEFINED
+#define _7ZIP_SIZET_DEFINED
+#ifdef _LZMA_SYSTEM_SIZE_T
+#include <stddef.h>
+typedef size_t SizeT;
+#else
+typedef UInt32 SizeT;
+#endif
+#endif
+
+#endif
diff --git a/cfe/cfe/lzma/Makefile b/cfe/cfe/lzma/Makefile
new file mode 100755
index 0000000..3611459
--- /dev/null
+++ b/cfe/cfe/lzma/Makefile
@@ -0,0 +1,5 @@
+
+BSPOBJS += \
+ dcapi.o \
+ LzmaDecode.o
+
diff --git a/cfe/cfe/lzma/dcapi.c b/cfe/cfe/lzma/dcapi.c
new file mode 100755
index 0000000..b8f59b0
--- /dev/null
+++ b/cfe/cfe/lzma/dcapi.c
@@ -0,0 +1,50 @@
+#include "LzmaDecode.h"
+#include "bcm63xx_util.h"
+#include "lib_malloc.h"
+
+#define LZMA_ORIGSIZE_SIZE 8
+
+int decompressLZMA(unsigned char *in, unsigned insize, unsigned char *out, unsigned outsize);
+
+// Call ANSI C LZMA decoder to decompress a LZMA block
+int decompressLZMA(unsigned char *in, unsigned insize, unsigned char *out, unsigned outsize)
+{
+
+ SizeT inProcessed, outProcessed;
+ unsigned origsize;
+ int ret;
+ CLzmaDecoderState state;
+
+ ret = LzmaDecodeProperties(&state.Properties, in, LZMA_PROPERTIES_SIZE);
+ if (ret != LZMA_RESULT_OK) {
+ return ret;
+ }
+ in += LZMA_PROPERTIES_SIZE;
+
+ state.Probs = (CProb *)KMALLOC(LzmaGetNumProbs(&state.Properties) * sizeof(CProb), 0);
+ if (!state.Probs) {
+ return 1001;
+ }
+
+ if (in[4]==0 && in[5]==0 && in[6]==0 && in[7]==0) { // uncompressed size < 4GB (should be)
+ origsize = in[0] | (in[1] << 8) | (in[2] << 16) | (in[3] << 24);
+ in += LZMA_ORIGSIZE_SIZE;
+ if (origsize <= outsize) {
+ ret = LzmaDecode(&state, in, insize, &inProcessed, out, origsize, &outProcessed);
+ }
+ else {
+ // output buffer too small
+ ret = 1000;
+ }
+ }
+ else { // uncompressed size > 4GB, old lzma format or corrupted image, assume old format here
+ printf("LZMA: Prossible old LZMA format, trying to decompress..\n");
+ LzmaDecode(&state, in, insize, &inProcessed, out, outsize, &outProcessed);
+ ret = 0; // It would return an error code as the output buffer size doesn't match. We need to ignore the code.
+ }
+
+ KFREE(state.Probs);
+
+ return ret;
+}
+
diff --git a/cfe/cfe/main/cfe.mk b/cfe/cfe/main/cfe.mk
new file mode 100644
index 0000000..05b16b6
--- /dev/null
+++ b/cfe/cfe/main/cfe.mk
@@ -0,0 +1,301 @@
+
+#
+# CFE's version number
+#
+
+include ${TOP}/main/cfe_version.mk
+
+#
+# Default values for certain parameters
+#
+
+CFG_MLONG64 ?= 0
+CFG_LITTLE ?= 0
+CFG_RELOC ?= 0
+CFG_UNCACHED ?= 0
+CFG_NEWRELOC ?= 0
+CFG_BOOTRAM ?= 0
+CFG_VGACONSOLE ?= 0
+CFG_PCI ?= 1
+CFG_LDT_REV_017 ?= 0
+CFG_ZLIB ?= 0
+CFG_BIENDIAN ?= 0
+CFG_DOWNLOAD ?= 0
+CFG_RAMAPP ?= 0
+CFG_USB ?= 0
+
+#
+# Paths to other parts of the firmware. Everything's relative to ${TOP}
+# so that you can actually do a build anywhere you want.
+#
+
+ARCH_TOP = ${TOP}/arch/${ARCH}
+ARCH_SRC = ${ARCH_TOP}/common/src
+ARCH_INC = ${ARCH_TOP}/common/include
+CPU_SRC = ${ARCH_TOP}/cpu/${CPU}/src
+CPU_INC = ${ARCH_TOP}/cpu/${CPU}/include
+
+#
+# It's actually optional to have a 'board'
+# directory. If you don't specify BOARD,
+# don't include the files.
+#
+
+ifneq ("$(strip ${BOARD})","")
+BOARD_SRC = ${ARCH_TOP}/board/${BOARD}/src
+BOARD_INC = ${ARCH_TOP}/board/${BOARD}/include
+endif
+
+#
+# Preprocessor defines for CFE's version number
+#
+
+VDEF = -DCFE_VER_MAJ=${CFE_VER_MAJ} -DCFE_VER_MIN=${CFE_VER_MIN} -DCFE_VER_ECO=${CFE_VER_ECO}
+
+#
+# Construct the list of paths that will eventually become the include
+# paths and VPATH
+#
+
+SRCDIRS = ${ARCH_SRC} ${CPU_SRC} ${BOARD_SRC} ${TOP}/main ${TOP}/vendor ${TOP}/include ${TOP}/net ${TOP}/dev ${TOP}/pci ${TOP}/ui ${TOP}/lib ${TOP}/common ${TOP}/verif
+
+CFE_INC = ${TOP}/include ${TOP}/pci ${TOP}/net
+
+ifeq ($(strip ${CFG_VGACONSOLE}),1)
+SRCDIRS += ${TOP}/x86emu ${TOP}/pccons
+CFE_INC += ${TOP}/x86emu ${TOP}/pccons
+endif
+
+ifeq ($(strip ${CFG_VAPI}),1)
+SRCDIRS += ${TOP}/verif
+CFE_INC += ${TOP}/verif
+endif
+
+ifeq ($(strip ${CFG_ZLIB}),1)
+SRCDIRS += ${TOP}/zlib
+CFE_INC += ${TOP}/zlib
+endif
+
+
+INCDIRS = $(patsubst %,-I%,$(subst :, ,$(ARCH_INC) $(CPU_INC) $(BOARD_INC) $(CFE_INC)))
+
+VPATH = $(SRCDIRS)
+
+#
+# Bi-endian support: If we're building the little-endian
+# version, use a different linker script so we can locate the
+# ROM at a higher address. You'd think we could do this with
+# normal linker command line switches, but there appears to be no
+# command-line way to override the 'AT' qualifier in the linker script.
+#
+
+CFG_TEXTAT1MB=0
+ifeq ($(strip ${CFG_BIENDIAN}),1)
+ ifeq ($(strip ${CFG_LITTLE}),1)
+ CFG_TEXTAT1MB=1
+ endif
+endif
+
+
+#
+# Configure tools and basic tools flags. This include sets up
+# macros for calling the C compiler, basic flags,
+# and linker scripts.
+#
+
+include ${ARCH_SRC}/tools.mk
+
+#
+# Add some common flags that are used on any architecture.
+#
+
+CFLAGS += -I. $(INCDIRS)
+CFLAGS += -D_CFE_ ${VDEF} -DCFG_BOARDNAME=\"${CFG_BOARDNAME}\"
+
+#
+# Gross - allow more options to be supplied from command line
+#
+
+ifdef CFG_OPTIONS
+OPTFLAGS = $(patsubst %,-D%,$(subst :, ,$(CFG_OPTIONS)))
+CFLAGS += ${OPTFLAGS}
+endif
+
+
+#
+# This is the makefile's main target. Note that we actually
+# do most of the work in 'ALL' not 'all', since we include
+# other makefiles after this point.
+#
+
+all : build_date.c makereg pcidevs_data2.h ALL
+
+#
+# Macros that expand to the list of arch-independent files
+#
+
+DEVOBJS = dev_flash.o dev_newflash.o dev_null.o dev_promice.o \
+ dev_ide_common.o dev_ns16550.o dev_ds17887clock.o
+LIBOBJS = lib_malloc.o lib_printf.o lib_queue.o lib_string.o lib_string2.o \
+ lib_arena.o lib_misc.o lib_setjmp.o lib_qsort.o lib_hssubr.o lib_physio.o
+NETOBJS = net_ether.o net_arp.o net_ip.o net_udp.o net_api.o net_dns.o \
+ net_dhcp.o net_tftp.o net_icmp.o net_tcp.o net_tcpbuf.o dev_tcpconsole.o
+CFEOBJS = env_subr.o cfe_attach.o cfe_iocb_dispatch.o cfe_devfuncs.o \
+ nvram_subr.o cfe_console.o cfe_main.o cfe_mem.o cfe_timer.o \
+ cfe_background.o cfe_error.o build_date.o \
+ cfe_rawfs.o cfe_zlibfs.o cfe_xreq.o cfe_fatfs.o cfe_httpfs.o cfe_filesys.o cfe_boot.o \
+ cfe_autoboot.o cfe_ldr_elf.o cfe_ldr_raw.o cfe_ldr_srec.o cfe_loader.o url.o \
+ cfe_savedata.o
+UIOBJS = ui_command.o ui_cmddisp.o ui_envcmds.o ui_devcmds.o \
+ ui_netcmds.o ui_tcpcmds.o ui_memcmds.o ui_loadcmds.o ui_pcicmds.o \
+ ui_examcmds.o ui_flash.o ui_misccmds.o \
+ ui_test_disk.o ui_test_ether.o ui_test_flash.o ui_test_uart.o
+
+#
+# Add more object files if we're supporting PCI
+#
+
+ifeq ($(strip ${CFG_PCI}),1)
+PCIOBJS = pciconf.o ldtinit.o pci_subr.o
+PCIOBJS += pci_devs.o
+DEVOBJS += dev_sp1011.o dev_ht7520.o
+DEVOBJS += dev_ide_pci.o dev_ns16550_pci.o
+DEVOBJS += dev_tulip.o dev_dp83815.o
+CFLAGS += -DCFG_PCI=1
+ifeq ($(strip ${CFG_LDT_REV_017}),1)
+CFLAGS += -DCFG_LDT_REV_017=1
+endif
+ifeq ($(strip ${CFG_DOWNLOAD}),1)
+DEVOBJS += dev_bcm1250.o download.data
+CFLAGS += -DCFG_DOWNLOAD=1
+endif
+endif
+
+#
+# If doing bi-endian, add the compiler switch to change
+# the way the vectors are generated. These switches are
+# only added to the big-endian portion of the ROM,
+# which is located at the real boot vector.
+#
+
+ifeq ($(strip ${CFG_BIENDIAN}),1)
+ ifeq ($(strip ${CFG_LITTLE}),0)
+ CFLAGS += -DCFG_BIENDIAN=1
+ endif
+endif
+
+#
+# Include the makefiles for the architecture-common, cpu-specific,
+# and board-specific directories. Each of these will supply
+# some files to "ALLOBJS". The BOARD directory is optional
+# as some ports are so simple they don't need boad-specific stuff.
+#
+
+include ${ARCH_SRC}/Makefile
+include ${CPU_SRC}/Makefile
+
+ifneq ("$(strip ${BOARD})","")
+include ${BOARD_SRC}/Makefile
+endif
+
+#
+# Add the common object files here.
+#
+
+ALLOBJS += $(LIBOBJS) $(DEVOBJS) $(CFEOBJS) $(VENOBJS) $(UIOBJS) $(NETOBJS) $(PCIOBJS)
+
+#
+# VAPI continues to be a special case.
+#
+
+ifeq ($(strip ${CFG_VAPI}),1)
+include ${TOP}/verif/Makefile
+endif
+
+#
+# USB support
+#
+
+ifeq ($(strip ${CFG_USB}),1)
+SRCDIRS += ${TOP}/usb
+CFE_INC += ${TOP}/usb
+include ${TOP}/usb/Makefile
+endif
+
+#
+# If we're doing the VGA console thing, pull in the x86 emulator
+# and the pcconsole subsystem
+#
+
+ifeq ($(strip ${CFG_VGACONSOLE}),1)
+include ${TOP}/x86emu/Makefile
+include ${TOP}/pccons/Makefile
+endif
+
+#
+# If we're including ZLIB, then add its makefile.
+#
+
+ifeq ($(strip ${CFG_ZLIB}),1)
+include ${TOP}/zlib/Makefile
+CFLAGS += -DCFG_ZLIB=1 -DMY_ZCALLOC -DNO_MEMCPY
+endif
+
+#
+# Vendor extensions come next - they live in their own directory.
+#
+
+include ${TOP}/vendor/Makefile
+
+.PHONY : all
+.PHONY : ALL
+.PHONY : build_date.c
+
+#
+# Build the local tools that we use to construct other source files
+#
+
+mkpcidb : ${TOP}/hosttools/mkpcidb.c
+ gcc -o mkpcidb ${TOP}/hosttools/mkpcidb.c
+
+memconfig : ${TOP}/hosttools/memconfig.c
+ gcc -o memconfig -D_MCSTANDALONE_ -D_MCSTANDALONE_NOISY_ -I${TOP}/arch/mips/cpu/sb1250/include ${TOP}/hosttools/memconfig.c ${TOP}/arch/${ARCH}/cpu/${CPU}/src/sb1250_draminit.c
+
+pcidevs_data2.h : mkpcidb ${TOP}/pci/pcidevs_data.h
+ ./mkpcidb > pcidevs_data2.h
+
+mkflashimage : ${TOP}/hosttools/mkflashimage.c
+ gcc -o mkflashimage -I${TOP}/include ${TOP}/hosttools/mkflashimage.c
+
+pci_subr.o : ${TOP}/pci/pci_subr.c pcidevs_data2.h
+
+build_date.c :
+ echo "const char *builddate = \"`date`\";" > build_date.c
+ echo "const char *builduser = \"`whoami`@`hostname`\";" >> build_date.c
+
+#
+# Make a define for the board name
+#
+
+CFLAGS += -D_$(patsubst "%",%,${CFG_BOARDNAME})_
+
+LIBCFE = libcfe.a
+
+%.o : %.c
+ $(GCC) $(CFLAGS) -o $@ $<
+
+%.o : %.S
+ $(GCC) $(CFLAGS) -o $@ $<
+
+#
+# This rule constructs "libcfe.a" which contains most of the object
+# files.
+#
+
+$(LIBCFE) : $(ALLOBJS)
+ rm -f $(LIBCFE)
+ $(AR) cr $(LIBCFE) $(ALLOBJS)
+ $(RANLIB) $(LIBCFE)
+
+
+
diff --git a/cfe/cfe/main/cfe_attach.c b/cfe/cfe/main/cfe_attach.c
new file mode 100644
index 0000000..1235d6e
--- /dev/null
+++ b/cfe/cfe/main/cfe_attach.c
@@ -0,0 +1,265 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Device Attach routines File: cfe_attach.c
+ *
+ * This module manages the list of device drivers. When a driver
+ * is probed, it can call cfe_attach to create actual device
+ * instances. The routines in this module manage the
+ * device list and the assignment of device names.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define CFE_MAX_DEVINST 64 /* max # of instances of devices */
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+/*
+ * Our device list.
+ */
+
+queue_t cfe_devices = {&cfe_devices, &cfe_devices};
+
+/* *********************************************************************
+ * cfe_finddev(name)
+ *
+ * Locate a device in the device list by its name and return
+ * a pointer to the device structure.
+ *
+ * Input parameters:
+ * name - name of device, e.g., "uart0"
+ *
+ * Return value:
+ * cfe_device_t pointer or NULL
+ ********************************************************************* */
+
+cfe_device_t *cfe_finddev(char *name)
+{
+ queue_t *qb;
+ cfe_device_t *dev;
+
+ for (qb = cfe_devices.q_next; qb != &cfe_devices; qb = qb->q_next) {
+ dev = (cfe_device_t *) qb;
+ if (strcmp(dev->dev_fullname,name) == 0) {
+ return dev;
+ }
+ }
+
+ return NULL;
+}
+
+
+/* *********************************************************************
+ * cfe_device_reset()
+ *
+ * Call all the "reset" methods in the devices on the device
+ * list. Note that the methods get called even when the
+ * devices are closed!
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_device_reset(void)
+{
+ queue_t *qb;
+ cfe_device_t *dev;
+
+ for (qb = cfe_devices.q_next; qb != &cfe_devices; qb = qb->q_next) {
+ dev = (cfe_device_t *) qb;
+ if (dev->dev_dispatch->dev_reset) {
+ (*(dev->dev_dispatch->dev_reset))(dev->dev_softc);
+ }
+ }
+}
+
+/* *********************************************************************
+ * cfe_attach_idx(drv,idx,softc,bootinfo,description)
+ *
+ * Add a device to the device list at a specific index. This
+ * is mainly used for devices like SCSI disks or CD-ROMs so
+ * we can use an index that matches the target ID or LUN.
+ *
+ * Input parameters:
+ * drv - driver structure (from the device driver module)
+ * idx - requested index (e.g., uartn where 'n' is the idx)
+ * softc - Unique information maintained for this device
+ * bootinfo - suffix for long form of the device name. For
+ * example, scsi0.3.1 might mean SCSI controller
+ * 0, device ID 3, LUN 1. The bootinfo would be
+ * "3.1"
+ * description - something nice to say for the devices command
+ *
+ * Return value:
+ * 0 if device has already been added at this index
+ * <0 for other problems
+ * 1 if we were successful.
+ ********************************************************************* */
+
+int cfe_attach_idx(cfe_driver_t *drv,int idx,void *softc,
+ char *bootinfo,char *description)
+{
+ char name[64];
+ cfe_device_t *dev;
+
+ xsprintf(name,"%s%d",drv->drv_bootname,idx);
+
+ if (bootinfo) {
+ strcat(name,".");
+ strcat(name,bootinfo);
+ }
+
+ if (cfe_finddev(name) != NULL) {
+ return 0;
+ }
+
+ dev = (cfe_device_t *) KMALLOC(sizeof(cfe_device_t),0);
+ if (!dev) return -1;
+
+ dev->dev_fullname = strdup(name);
+ dev->dev_softc = softc;
+ dev->dev_class = drv->drv_class;
+ dev->dev_dispatch = drv->drv_dispatch;
+ dev->dev_description = description ? strdup(description) : NULL;
+ dev->dev_opencount = 0;
+
+ q_enqueue(&cfe_devices,(queue_t *) dev);
+
+ return 1;
+
+}
+
+
+
+/* *********************************************************************
+ * cfe_attach(drv,softc,bootinfo,description
+ *
+ * Add a device to the system. This is a callback from the
+ * probe routine, and is used to actually add devices to CFE's
+ * device list.
+ *
+ * Input parameters:
+ * drv - driver structure (from the device driver module)
+ * softc - Unique information maintained for this device
+ * bootinfo - suffix for long form of the device name. For
+ * example, scsi0.3.1 might mean SCSI controller
+ * 0, device ID 3, LUN 1. The bootinfo would be
+ * "3.1"
+ * description - something nice to say for the devices command
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_attach(cfe_driver_t *drv,void *softc,
+ char *bootinfo,
+ char *description)
+{
+ int idx;
+ int res;
+
+ /*
+ * Try device indicies 0..CFE_MAX_DEVINST to assign a unique
+ * device name for this device. This is a really braindead way to
+ * do this, but how many devices are we expecting anyway?
+ */
+
+ for (idx = 0; idx < CFE_MAX_DEVINST; idx++) {
+
+ res = cfe_attach_idx(drv,idx,softc,bootinfo,description);
+
+ if (res < 0) break; /* out of memory or other badness */
+ if (res > 0) break; /* success! */
+ /* otherwise, try again, slot is taken */
+ }
+
+}
+
+/* *********************************************************************
+ * cfe_attach_init()
+ *
+ * Initialize this module.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+void cfe_attach_init(void)
+{
+ q_init(&(cfe_devices));
+}
+
+
+/* *********************************************************************
+ * cfe_device_name(ctx)
+ *
+ * Given a device context, return a device name
+ *
+ * Input parameters:
+ * ctx - context
+ *
+ * Return value:
+ * name
+ ********************************************************************* */
+
+char *cfe_device_name(cfe_devctx_t *ctx)
+{
+ return ctx->dev_dev->dev_fullname;
+}
diff --git a/cfe/cfe/main/cfe_autoboot.c b/cfe/cfe/main/cfe_autoboot.c
new file mode 100644
index 0000000..14f3d3c
--- /dev/null
+++ b/cfe/cfe/main/cfe_autoboot.c
@@ -0,0 +1,456 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Automatic OS bootstrap File: cfe_autoboot.c
+ *
+ * This module handles OS bootstrap stuff. We use this version
+ * to do "automatic" booting; walking down a list of possible boot
+ * options, trying them until something good happens.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_devfuncs.h"
+#include "cfe_timer.h"
+
+#include "cfe_error.h"
+
+#include "env_subr.h"
+#include "cfe.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+
+#include "net_api.h"
+#include "cfe_fileops.h"
+#include "cfe_bootblock.h"
+#include "bsp_config.h"
+#include "cfe_boot.h"
+
+#include "cfe_loader.h"
+
+#include "cfe_autoboot.h"
+
+/* *********************************************************************
+ * data
+ ********************************************************************* */
+
+queue_t cfe_autoboot_list = {&cfe_autoboot_list,&cfe_autoboot_list};
+
+extern cfe_loadargs_t cfe_loadargs; /* from cfe_boot.c */
+extern const char *bootvar_device;
+extern const char *bootvar_file;
+extern const char *bootvar_flags;
+
+extern char *varchars;
+
+/* *********************************************************************
+ * macroexpand(instr,outstr)
+ *
+ * Expand environment variables in "instr" to "outstr"
+ *
+ * Input parameters:
+ * instr - to be expanded
+ * outstr - expanded.
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void macroexpand(char *instr,char *outstr)
+{
+ char macroname[50];
+ char *m;
+
+ while (*instr) {
+ if (*instr == '$') {
+ instr++;
+ m = macroname;
+ while (*instr && strchr(varchars,*instr)) {
+ *m++ = *instr++;
+ }
+ *m = '\0';
+ m = env_getenv(macroname);
+ if (m) {
+ while (*m) *outstr++ = *m++;
+ }
+ }
+ else {
+ *outstr++ = *instr++;
+ }
+ }
+
+ *outstr = '\0';
+}
+
+/* *********************************************************************
+ * cfe_tryauto_common(method,loadargs)
+ *
+ * Common portion of autoboot
+ *
+ * Input parameters:
+ * method - details on device to boot from
+ * filename - canonical name of file to load
+ * loadargs - cfe_loadargs_t of digested load parameters.
+ *
+ * Return value:
+ * does not return if successful
+ ********************************************************************* */
+
+static int cfe_tryauto_common(cfe_autoboot_method_t *method,
+ char *filename,
+ cfe_loadargs_t *la)
+{
+ int res;
+
+ la->la_filename = filename;
+ la->la_options = env_getenv(bootvar_flags);
+ la->la_filesys = method->ab_filesys;
+ la->la_device = method->ab_dev;
+ la->la_flags = method->ab_flags | LOADFLG_NOISY | LOADFLG_EXECUTE;
+ la->la_address = 0;
+ la->la_maxsize = 0;
+ la->la_entrypt = 0;
+
+ /* okay, go for it. */
+
+ xprintf("Loader:%s Filesys:%s Dev:%s File:%s Options:%s\n",
+ method->ab_loader,la->la_filesys,la->la_device,la->la_filename,la->la_options);
+
+ res = cfe_boot(method->ab_loader,&cfe_loadargs);
+
+ return res;
+
+}
+
+
+/* *********************************************************************
+ * cfe_tryauto_network(method)
+ *
+ * Try to autoboot from a network device.
+ *
+ * Input parameters:
+ * method - details on device to boot from
+ *
+ * Return value:
+ * does not return unless there is an error
+ ********************************************************************* */
+
+#if CFG_NETWORK
+static int cfe_tryauto_network(cfe_autoboot_method_t *method)
+{
+ int res;
+ dhcpreply_t *reply = NULL;
+ cfe_loadargs_t *la = &cfe_loadargs;
+ char buffer[512];
+ char *x;
+
+ /*
+ * First turn off any network interface that is currently active.
+ */
+
+ net_uninit();
+
+ /*
+ * Now activate the network hardware.
+ */
+
+ res = net_init(method->ab_dev);
+ if (res < 0) {
+ printf("Could not initialize network device %s: %s\n",
+ method->ab_dev,
+ cfe_errortext(res));
+ return res;
+ }
+
+ /*
+ * Do a DHCP query.
+ */
+
+ res = dhcp_bootrequest(&reply);
+ if (res < 0) {
+ printf("DHCP request failed on device %s: %s\n",method->ab_dev,
+ cfe_errortext(res));
+ net_uninit();
+ return res;
+ }
+
+ net_setparam(NET_IPADDR,reply->dr_ipaddr);
+ net_setparam(NET_NETMASK,reply->dr_netmask);
+ net_setparam(NET_GATEWAY,reply->dr_gateway);
+ net_setparam(NET_NAMESERVER,reply->dr_nameserver);
+ net_setparam(NET_DOMAIN,reply->dr_domainname);
+
+ /* Set all our environment variables. */
+ net_setnetvars();
+ dhcp_set_envvars(reply);
+
+ if (reply) dhcp_free_reply(reply);
+
+ /*
+ * Interface is now configured and ready, we can
+ * load programs now.
+ */
+
+ /*
+ * Construct the file name to load. If the method does not
+ * specify a file name directly, get it from DHCP.
+ *
+ * For network booting, the format of the file name
+ * is 'hostname:filename'
+ *
+ * If the method's filename includes a hostname, ignore
+ * BOOT_SERVER. Otherwise, combine BOOT_SERVER with the
+ * filename. This way we can provide the name here
+ * but have the file come off the server specified in the
+ * DHCP message.
+ */
+
+ if (method->ab_file && strchr(method->ab_file,':')) {
+ macroexpand(method->ab_file,buffer);
+ }
+ else {
+ buffer[0] = '\0';
+ x = env_getenv("BOOT_SERVER");
+ if (x) {
+ strcat(buffer,x);
+ strcat(buffer,":");
+ }
+
+ x = method->ab_file;
+ if (!x) x = env_getenv(bootvar_file);
+ if (x) {
+ strcat(buffer,x);
+ }
+ }
+
+ /* Okay, do it. */
+
+ cfe_tryauto_common(method,buffer,la);
+
+ /* If we get here, something bad happened. */
+
+ net_uninit();
+
+ return res;
+
+}
+
+#endif
+
+
+/* *********************************************************************
+ * cfe_tryauto_disk(method)
+ *
+ * Try to autoboot from a disk device.
+ *
+ * Input parameters:
+ * method - details on device to boot from
+ *
+ * Return value:
+ * does not return unless there is an error
+ ********************************************************************* */
+static int cfe_tryauto_disk(cfe_autoboot_method_t *method)
+{
+ int res;
+ cfe_loadargs_t *la = &cfe_loadargs;
+ char buffer[512];
+ char *filename;
+
+ buffer[0] = '\0';
+
+ if (method->ab_file) {
+ macroexpand(method->ab_file,buffer);
+ filename = buffer;
+ }
+ else {
+ filename = env_getenv("BOOT_FILE");
+ if (filename) strcpy(buffer,filename);
+ }
+
+ res = cfe_tryauto_common(method,filename,la);
+
+ return res;
+}
+
+/* *********************************************************************
+ * cfe_tryauto(method)
+ *
+ * Try a single autoboot method.
+ *
+ * Input parameters:
+ * method - autoboot method to try
+ *
+ * Return value:
+ * does not return if bootstrap is successful
+ * else error code
+ ********************************************************************* */
+
+static int cfe_tryauto(cfe_autoboot_method_t *method)
+{
+ switch (method->ab_type) {
+#if CFG_NETWORK
+ case CFE_AUTOBOOT_NETWORK:
+ return cfe_tryauto_network(method);
+ break;
+#endif
+
+ case CFE_AUTOBOOT_DISK:
+ case CFE_AUTOBOOT_RAW:
+ return cfe_tryauto_disk(method);
+ break;
+ }
+
+ return -1;
+}
+
+/* *********************************************************************
+ * cfe_autoboot(dev,flags)
+ *
+ * Try to perform an automatic system bootstrap
+ *
+ * Input parameters:
+ * dev - if not NULL, restrict bootstrap to named device
+ * flags - controls behaviour of cfe_autoboot
+ *
+ * Return value:
+ * should not return if bootstrap is successful, otherwise
+ * error code
+ ********************************************************************* */
+int cfe_autoboot(char *dev,int flags)
+{
+ queue_t *qb;
+ cfe_autoboot_method_t *method;
+ int res;
+ cfe_timer_t timer;
+ int forever;
+ int pollconsole;
+
+ forever = (flags & CFE_AUTOFLG_TRYFOREVER) ? 1 : 0;
+ pollconsole = (flags & CFE_AUTOFLG_POLLCONSOLE) ? 1 : 0;
+
+ do { /* potentially forever */
+ for (qb = cfe_autoboot_list.q_next; qb != &cfe_autoboot_list; qb = qb->q_next) {
+
+ method = (cfe_autoboot_method_t *) qb;
+
+ /*
+ * Skip other devices if we passed in a specific one.
+ */
+
+ if (dev && (strcmp(dev,method->ab_dev) != 0)) continue;
+
+ printf("\n*** Autoboot: Trying device '%s' ", method->ab_dev);
+ if (method->ab_file) printf("file %s ",method->ab_file);
+ printf("(%s,%s)\n\n",method->ab_dev,method->ab_filesys,method->ab_loader);
+
+ /*
+ * Scan keyboard if requested.
+ */
+ if (pollconsole) {
+ TIMER_SET(timer,CFE_HZ);
+ while (!TIMER_EXPIRED(timer)) {
+ POLL();
+ if (console_status()) goto done;
+ }
+ }
+
+ /*
+ * Try something. may not return.
+ */
+
+ res = cfe_tryauto(method);
+ }
+ } while (forever);
+
+ /* bail. */
+done:
+
+ printf("\n*** Autoboot failed.\n\n");
+
+ return -1;
+}
+
+
+/* *********************************************************************
+ * cfe_add_autoboot(type,flags,dev,loader,filesys,file)
+ *
+ * Add an autoboot method to the table.
+ * This is typically called in the board_finalinit one or more
+ * times to provide a list of bootstrap methods to try for autoboot
+ *
+ * Input parameters:
+ * type - CFE_AUTOBOOT_xxx (disk,network,raw)
+ * flags - loader flags (LOADFLG_xxx)
+ * loader - loader string (elf, raw, srec)
+ * filesys - file system string (raw, tftp, fat)
+ * file - name of file to load (if null, will try to guess)
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+int cfe_add_autoboot(int type,int flags,char *dev,char *loader,char *filesys,char *file)
+{
+ cfe_autoboot_method_t *method;
+
+ method = (cfe_autoboot_method_t *) KMALLOC(sizeof(cfe_autoboot_method_t),0);
+
+ if (!method) return CFE_ERR_NOMEM;
+
+ method->ab_type = type;
+ method->ab_flags = flags;
+ method->ab_dev = dev;
+ method->ab_loader = loader;
+ method->ab_filesys = filesys;
+ method->ab_file = file;
+
+ q_enqueue(&cfe_autoboot_list,(queue_t *)method);
+ return 0;
+}
diff --git a/cfe/cfe/main/cfe_background.c b/cfe/cfe/main/cfe_background.c
new file mode 100644
index 0000000..9a64e0a
--- /dev/null
+++ b/cfe/cfe/main/cfe_background.c
@@ -0,0 +1,174 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Timer routines File: cfe_timer.c
+ *
+ * This module manages the list of routines to call periodically
+ * during "background processing." CFE has no interrupts or
+ * multitasking, so this is just where all the polling routines
+ * get called from.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+
+#include "cfe_timer.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define MAX_BACKGROUND_TASKS 16
+
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+static void (*cfe_bg_tasklist[MAX_BACKGROUND_TASKS])(void *);
+static void *cfe_bg_args[MAX_BACKGROUND_TASKS];
+
+
+/* *********************************************************************
+ * cfe_bg_init()
+ *
+ * Initialize the background task list
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_bg_init(void)
+{
+ memset(cfe_bg_tasklist,0,sizeof(cfe_bg_tasklist));
+}
+
+
+/* *********************************************************************
+ * cfe_bg_add(func,arg)
+ *
+ * Add a function to be called periodically in the background
+ * polling loop.
+ *
+ * Input parameters:
+ * func - function pointer
+ * arg - arg to pass to function
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_bg_add(void (*func)(void *x),void *arg)
+{
+ int idx;
+
+ for (idx = 0; idx < MAX_BACKGROUND_TASKS; idx++) {
+ if (cfe_bg_tasklist[idx] == NULL) {
+ cfe_bg_tasklist[idx] = func;
+ cfe_bg_args[idx] = arg;
+ return;
+ }
+ }
+}
+
+/* *********************************************************************
+ * cfe_bg_remove(func)
+ *
+ * Remove a function from the background polling loop
+ *
+ * Input parameters:
+ * func - function pointer
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_bg_remove(void (*func)(void *))
+{
+ int idx;
+
+ for (idx = 0; idx < MAX_BACKGROUND_TASKS; idx++) {
+ if (cfe_bg_tasklist[idx] == func) break;
+ }
+
+ if (idx == MAX_BACKGROUND_TASKS) return;
+
+ for (; idx < MAX_BACKGROUND_TASKS-1; idx++) {
+ cfe_bg_tasklist[idx] = cfe_bg_tasklist[idx+1];
+ cfe_bg_args[idx] = cfe_bg_args[idx+1];
+ }
+
+ cfe_bg_tasklist[idx] = NULL;
+ cfe_bg_args[idx] = NULL;
+}
+
+
+/* *********************************************************************
+ * background()
+ *
+ * The main loop and other places that wait for stuff call
+ * this routine to make sure the background handlers get their
+ * time.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void background(void)
+{
+ int idx;
+ void (*func)(void *arg);
+
+ for (idx = 0; idx < MAX_BACKGROUND_TASKS; idx++) {
+ func = cfe_bg_tasklist[idx];
+ if (func == NULL) break;
+ (*func)(cfe_bg_args[idx]);
+ }
+}
diff --git a/cfe/cfe/main/cfe_boot.c b/cfe/cfe/main/cfe_boot.c
new file mode 100644
index 0000000..12fecaa
--- /dev/null
+++ b/cfe/cfe/main/cfe_boot.c
@@ -0,0 +1,248 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * OS bootstrap File: cfe_boot.c
+ *
+ * This module handles OS bootstrap stuff
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_devfuncs.h"
+#include "cfe_timer.h"
+
+#include "cfe_error.h"
+
+#include "env_subr.h"
+#include "cfe.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+
+#include "net_api.h"
+#include "cfe_fileops.h"
+#include "cfe_bootblock.h"
+#include "bsp_config.h"
+#include "cfe_boot.h"
+
+#include "cfe_loader.h"
+
+#if CFG_UI
+extern int ui_docommands(char *buf);
+#endif
+
+/* *********************************************************************
+ * data
+ ********************************************************************* */
+
+const char *bootvar_device = "BOOT_DEVICE";
+const char *bootvar_file = "BOOT_FILE";
+const char *bootvar_flags = "BOOT_FLAGS";
+
+cfe_loadargs_t cfe_loadargs;
+
+/* *********************************************************************
+ * splitpath(path,devname,filename)
+ *
+ * Split a path name (a boot path, in the form device:filename)
+ * into its parts
+ *
+ * Input parameters:
+ * path - pointer to path string
+ * devname - receives pointer to device name
+ * filename - receives pointer to file name
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void splitpath(char *path,char **devname,char **filename)
+{
+ char *x;
+
+ *devname = NULL;
+ *filename = NULL;
+
+ x = strchr(path,':');
+
+ if (!x) {
+ *devname = NULL; /* path consists of device name */
+ *filename = path;
+ }
+ else {
+ *x++ = '\0'; /* have both device and file name */
+ *filename = x;
+ *devname = path;
+ }
+}
+
+
+/* *********************************************************************
+ * cfe_go(la)
+ *
+ * Starts a previously loaded program. cfe_loadargs.la_entrypt
+ * must be set to the entry point of the program to be started
+ *
+ * Input parameters:
+ * la - loader args
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+void cfe_go(cfe_loadargs_t *la)
+{
+ if (la->la_entrypt == 0) {
+ xprintf("No program has been loaded.\n");
+ return;
+ }
+
+#if CFG_NETWORK
+ if (!(la->la_flags & LOADFLG_NOCLOSE)) {
+ if (net_getparam(NET_DEVNAME)) {
+ xprintf("Closing network.\n");
+ net_uninit();
+ }
+ }
+#endif
+
+ xprintf("Starting program at 0x%p\n",la->la_entrypt);
+
+ cfe_start(la->la_entrypt);
+}
+
+
+/* *********************************************************************
+ * cfe_boot(la)
+ *
+ * Bootstrap the system.
+ *
+ * Input parameters:
+ * la - loader arguments
+ *
+ * Return value:
+ * error, or does not return
+ ********************************************************************* */
+int cfe_boot(char *ldrname,cfe_loadargs_t *la)
+{
+ int res;
+
+ la->la_entrypt = 0;
+
+ if (la->la_flags & LOADFLG_NOISY) {
+ xprintf("Loading: ");
+ }
+
+ res = cfe_load_program(ldrname,la);
+
+ if (res < 0) {
+ if (la->la_flags & LOADFLG_NOISY) {
+ xprintf("Failed.\n");
+ }
+ return res;
+ }
+
+ /*
+ * Special case: If loading a batch file, just do the commands here
+ * and return. For batch files we don't want to set up the
+ * environment variables.
+ */
+
+ if (la->la_flags & LOADFLG_BATCH) {
+#if CFG_UI
+ ui_docommands((char *) la->la_entrypt);
+#endif
+ return 0;
+ }
+
+ /*
+ * Otherwise set up for running a real program.
+ */
+
+ if (la->la_flags & LOADFLG_NOISY) {
+ xprintf("Entry at 0x%p\n",la->la_entrypt);
+ }
+
+ /*
+ * Set up the environment variables for the bootstrap
+ */
+
+ if (la->la_device) {
+ env_setenv(bootvar_device,la->la_device,ENV_FLG_BUILTIN);
+ }
+ else {
+ env_delenv(bootvar_device);
+ }
+
+ if (la->la_filename) {
+ env_setenv(bootvar_file,la->la_filename,ENV_FLG_BUILTIN);
+ }
+ else {
+ env_delenv(bootvar_file);
+ }
+
+ if (la->la_options) {
+ env_setenv(bootvar_flags,la->la_options,ENV_FLG_BUILTIN);
+ }
+ else {
+ env_delenv(bootvar_flags);
+ }
+
+ /*
+ * Banzai! Run the program.
+ */
+
+ if ((la->la_flags & LOADFLG_EXECUTE) &&
+ (la->la_entrypt != 0)) {
+ cfe_go(la);
+ }
+
+ return 0;
+}
+
diff --git a/cfe/cfe/main/cfe_console.c b/cfe/cfe/main/cfe_console.c
new file mode 100755
index 0000000..a9464f1
--- /dev/null
+++ b/cfe/cfe/main/cfe_console.c
@@ -0,0 +1,1190 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Console Interface File: cfe_console.c
+ *
+ * This module contains high-level routines for dealing with
+ * the console (TTY-style) device.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include <stdarg.h>
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_timer.h"
+#include "cfe_error.h"
+#include "env_subr.h"
+#include "cfe_console.h"
+#include "cfe.h"
+
+#include "bsp_config.h"
+
+
+/*
+ * Escape sequences:
+ *
+ * Sequence Descr Emulator
+ *
+ * ESC [ A UP xterm
+ * ESC [ B DOWN xterm
+ * ESC [ C RIGHT xterm
+ * ESC [ D LEFT xterm
+ *
+ * ESC O P F1 xterm
+ * ESC O Q F2 xterm
+ * ESC O R F3 xterm
+ * ESC O S F4 xterm
+ *
+ * ESC [ 1 1 ~ F1 teraterm
+ * ESC [ 1 2 ~ F2 teraterm
+ * ESC [ 1 3 ~ F3 teraterm
+ * ESC [ 1 4 ~ F4 teraterm
+ *
+ * ESC [ 1 5 ~ F5 xterm,teraterm
+ * ESC [ 1 7 ~ F6 xterm,teraterm
+ * ESC [ 1 8 ~ F7 xterm,teraterm
+ * ESC [ 1 9 ~ F8 xterm,teraterm
+ * ESC [ 2 0 ~ F9 xterm,teraterm
+ * ESC [ 2 1 ~ F10 xterm,teraterm
+ * ESC [ 2 3 ~ F11 xterm,teraterm
+ * ESC [ 2 4 ~ F12 xterm,teraterm
+ *
+ * ESC [ 5 ~ PGUP xterm
+ * ESC [ 6 ~ PGDN xterm
+ * ESC [ F HOME xterm
+ * ESC [ H END xterm
+ *
+ * ESC [ 2 ~ HOME teraterm
+ * ESC [ 3 ~ PGUP teraterm
+ * ESC [ 5 ~ END teraterm
+ * ESC [ 6 ~ PGDN teraterm
+ *
+ */
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+
+#define CTRL(x) ((x)-'@')
+
+#define GETCHAR(x) while (console_read(&(x),1) != 1) { POLL(); }
+
+#define XTERM 0
+#define TERATERM 1
+
+#define MAXSAVELINES 30
+#define MSGQUEUEMAX 10 /* number of chunks of log to keep */
+#define MSGQUEUESIZE 256 /* size of each chunk of console log */
+
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef struct msgqueue_s { /* saved console log message */
+ queue_t link;
+ int len;
+ char data[MSGQUEUESIZE];
+} msgqueue_t;
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+#if !CFG_MINIMAL_SIZE
+int console_nextsave = 0;
+char *console_savedlines[MAXSAVELINES] = {0};
+static char *console_killbuffer = NULL;
+queue_t console_msgq = {&console_msgq,&console_msgq};
+static int console_buffer_flg = 0;
+static int console_mode = XTERM;
+
+static void console_flushbuffer(void);
+static void console_save(unsigned char *buffer,int length);
+
+#endif
+
+#if defined(CONFIG_MIPS_BRCM)
+int g_console_abort = 0;
+#endif
+int console_handle = -1;
+static int console_xprint(const char *str);
+char *console_name = NULL;
+static int console_inreadline = 0;
+static int console_redisplay = 0;
+
+/* *********************************************************************
+ * console_log(tmplt,...)
+ *
+ * Sort of like printf, but used during things that might be
+ * called in the polling loop. If you print out a message
+ * using this call and it happens to be printed while processing
+ * the console "readline" loop, the readline and the associated
+ * prompt will be redisplayed. Don't include the \r\n in the
+ * string to be displayed.
+ *
+ * Input parameters:
+ * tmplt, ... - printf parameters
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void console_log(const char *tmplt,...)
+{
+ char buffer[256];
+ va_list marker;
+ int count;
+
+ va_start(marker,tmplt);
+ count = xvsprintf(buffer,tmplt,marker);
+ va_end(marker);
+ xprintf("\r%s\033[J\r\n",buffer);
+
+ if (console_inreadline) console_redisplay = 1;
+}
+
+/* *********************************************************************
+ * console_open(name)
+ *
+ * Open the specified device and make it the console
+ *
+ * Input parameters:
+ * name - name of device
+ *
+ * Return value:
+ * 0 if ok, else return code.
+ * console_handle contains the console's handle
+ ********************************************************************* */
+
+int console_open(char *name)
+{
+#if CFG_MINIMAL_SIZE
+ if (console_handle != -1) {
+ console_close();
+ }
+
+ console_handle = cfe_open(name);
+ if (console_handle < 0) return CFE_ERR_DEVNOTFOUND;
+
+#else
+
+ int flushbuf;
+
+ console_name = NULL;
+
+ if (console_handle != -1) {
+ console_close();
+ }
+
+ flushbuf = console_buffer_flg;
+ console_buffer_flg = 0;
+
+ console_handle = cfe_open(name);
+ if (console_handle < 0) return CFE_ERR_DEVNOTFOUND;
+
+ console_name = name;
+ if (flushbuf) console_flushbuffer();
+#endif
+
+ return 0;
+}
+
+/* *********************************************************************
+ * console_close()
+ *
+ * Close the console device
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+int console_close(void)
+{
+ if (console_handle != -1) {
+ cfe_close(console_handle);
+ }
+
+ console_handle = -1;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * console_read(buffer,length)
+ *
+ * Read characters from the console.
+ *
+ * Input parameters:
+ * buffer - pointer to buffer to receive characters
+ * length - total size of the buffer
+ *
+ * Return value:
+ * number of characters received, or <0 if error code
+ ********************************************************************* */
+
+int console_read(char *buffer,int length)
+{
+ if (console_handle == -1) return -1;
+
+ return cfe_read(console_handle,(unsigned char*)buffer,length);
+}
+
+
+/* *********************************************************************
+ * console_write(buffer,length)
+ *
+ * Write text to the console. If the console is not open and
+ * we're "saving" text, put the text on the in-memory queue
+ *
+ * Input parameters:
+ * buffer - pointer to data
+ * length - number of characters to write
+ *
+ * Return value:
+ * number of characters written or <0 if error
+ ********************************************************************* */
+
+int console_write(char *buffer,int length)
+{
+ int res;
+
+#if !CFG_MINIMAL_SIZE
+ /*
+ * Buffer text if requested
+ */
+ if (console_buffer_flg) {
+ console_save(buffer,length);
+ return length;
+ }
+#endif
+
+ /*
+ * Do nothing if no console
+ */
+
+ if (console_handle == -1) return -1;
+
+ /*
+ * Write text to device
+ */
+
+ for (;;) {
+ res = cfe_write(console_handle,(unsigned char*)buffer,length);
+ if (res < 0) break;
+ buffer += res;
+ length -= res;
+ if (length == 0) break;
+ }
+
+ if (res < 0) return -1;
+ return 0;
+}
+
+/* *********************************************************************
+ * console_status()
+ *
+ * Return the status of input for the console.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0 if no characters are available
+ * 1 if characters are available.
+ ********************************************************************* */
+
+int console_status(void)
+{
+ if (console_handle == -1) return 0;
+
+ return cfe_inpstat(console_handle);
+}
+
+/* *********************************************************************
+ * console_xprint(str)
+ *
+ * printf callback for the console device. the "xprintf"
+ * routine ends up calling this. This routine also cooks the
+ * output, turning "\n" into "\r\n"
+ *
+ * Input parameters:
+ * str - string to write
+ *
+ * Return value:
+ * number of characters written
+ ********************************************************************* */
+
+static int console_xprint(const char *str)
+{
+ int count = 0;
+ int len;
+ const char *p;
+
+ /* Convert CR to CRLF as we write things out */
+
+ while ((p = strchr(str,'\n'))) {
+ console_write((char*)str,p-str);
+ console_write("\r\n",2);
+ count += (p-str);
+ str = p + 1;
+ }
+
+ len = strlen(str);
+ console_write((char*)str, len);
+ count += len;
+
+ return count;
+}
+
+
+/* *********************************************************************
+ * console_readline_noedit(str,len)
+ *
+ * A simple 'gets' type routine for the console. We support
+ * backspace and carriage return. No line editing support here,
+ * this routine is used in places where we don't want it.
+ *
+ * Input parameters:
+ * prompt - prompt string
+ * str - pointer to user buffer
+ * len - length of user buffer
+ *
+ * Return value:
+ * number of characters read (terminating newline is not
+ * placed in the buffer)
+ ********************************************************************* */
+
+int console_readline_noedit(char *prompt,char *str,int len)
+{
+ int reading = 1;
+ char ch;
+ int res = -1;
+ int idx = 0;
+
+ console_inreadline++;
+
+ if (prompt && *prompt) console_write(prompt,strlen(prompt));
+
+ POLL();
+ while (reading) {
+
+ /*
+ * If someone used console_log (above) or hit Control-C (below),
+ * redisplay the prompt and the string we've got so far.
+ */
+
+ if (console_redisplay) {
+ if (prompt && *prompt) console_write(prompt,strlen(prompt));
+ console_write(str,idx);
+ console_redisplay = 0;
+ continue;
+ }
+
+#if defined(CONFIG_MIPS_BRCM)
+
+ /*
+ * If a background process has set the global g_console_abort flag, stop
+ * reading from the keyboard.
+ */
+
+ if (g_console_abort) {
+ g_console_abort = 0;
+ break;
+ }
+
+#endif
+
+ /*
+ * if nobody's typed anything, keep polling
+ */
+
+ if (console_status() == 0) {
+ POLL();
+ continue;
+ }
+
+ /*
+ * Get the char from the keyboard
+ */
+
+ res = console_read(&ch,1);
+ if (res < 0) break;
+ if (res == 0) continue;
+
+ /*
+ * And dispatch it
+ */
+
+ switch (ch) {
+ case 3: /* Ctrl-C */
+ console_write("^C\r\n",4);
+ console_redisplay = 1;
+ idx = 0;
+ break;
+ case 0x7f:
+ case '\b':
+ if (idx > 0) {
+ idx--;
+ console_write("\b \b",3);
+ }
+ break;
+ case 21: /* Ctrl-U */
+ while (idx > 0) {
+ idx--;
+ console_write("\b \b",3);
+ }
+ break;
+ case '\r':
+ case '\n':
+ console_write("\r\n",2);
+ reading = 0;
+ break;
+ default:
+ if (ch >= ' ') {
+ if (idx < (len-1)) {
+ str[idx] = ch;
+ idx++;
+ console_write(&ch,1);
+ }
+ }
+ break;
+ }
+ }
+ POLL();
+
+ console_inreadline--;
+
+ str[idx] = 0;
+ return idx;
+}
+
+
+/* *********************************************************************
+ * cfe_set_console(name)
+ *
+ * This routine is usually called from the BSP's initialization
+ * module to set up the console device. We set the xprintf
+ * callback and open the console device. If we open a special
+ * magic console device (CFE_BUFFER_CONSOLE) the console subsystem
+ * will buffer text instead. A later call to cfe_set_console
+ * with a real console name will cause this text to be flushed.
+ *
+ * Input parameters:
+ * name - name of console device
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int cfe_set_console(char *name)
+{
+ xprinthook = console_xprint;
+
+#if !CFG_MINIMAL_SIZE
+ if (strcmp(name,CFE_BUFFER_CONSOLE) == 0) {
+ console_buffer_flg = 1;
+ return 0;
+ }
+#endif
+
+ if (name) {
+ int res;
+ res = env_setenv("BOOT_CONSOLE",name,
+ ENV_FLG_BUILTIN | ENV_FLG_READONLY | ENV_FLG_ADMIN);
+ return console_open(name);
+ }
+ return -1;
+}
+
+#if !CFG_MINIMAL_SIZE
+
+/* *********************************************************************
+ * console_flushbuffer()
+ *
+ * Flush queued (saved) console messages to the real console
+ * device. This is used if we need to delay console
+ * initialization until after other devices are initialized,
+ * for example, with a VGA console that won't work until
+ * after PCI initialization.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void console_flushbuffer(void)
+{
+ msgqueue_t *msg;
+ char *buffer;
+ int length;
+ int res;
+
+ /*
+ * Remove console messages from the queue
+ */
+
+ while ((msg = (msgqueue_t *) q_deqnext(&console_msgq))) {
+
+ buffer = msg->data;
+ length = msg->len;
+ res = 0;
+
+ /*
+ * Write each message to the console
+ */
+
+ for (;;) {
+ res = cfe_write(console_handle,buffer,length);
+ if (res < 0) break;
+ buffer += res;
+ length -= res;
+ if (length == 0) break;
+ }
+
+ /*
+ * Free the storage
+ */
+
+ KFREE(msg);
+ }
+}
+
+
+/* *********************************************************************
+ * console_save(buffer,length)
+ *
+ * This is used when we want to generate console output
+ * before the device is initialized. The console_save
+ * routine saves a copy of the log messages in a queue
+ * for later retrieval when the console device is open.
+ *
+ * Input parameters:
+ * buffer - message text to save
+ * length - number of bytes
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void console_save(unsigned char *buffer,int length)
+{
+ msgqueue_t *msg;
+
+ /*
+ * Get a pointer to the last message in the queue. If
+ * it's full, preprare to allocate a new one
+ */
+
+ msg = (msgqueue_t *) console_msgq.q_prev;
+ if (q_isempty(&(console_msgq)) || (msg->len == MSGQUEUESIZE)) {
+ msg = NULL;
+ }
+
+ /*
+ * Stuff characters into message chunks till we're done
+ */
+
+ while (length) {
+
+ /*
+ * New chunk
+ */
+ if (msg == NULL) {
+
+ msg = (msgqueue_t *) KMALLOC(sizeof(msgqueue_t),0);
+ if (msg == NULL) return;
+ msg->len = 0;
+ q_enqueue(&console_msgq,(queue_t *) msg);
+
+ /*
+ * Remove chunks to prevent chewing too much memory
+ */
+
+ while (q_count(&console_msgq) > MSGQUEUEMAX) {
+ msgqueue_t *dropmsg;
+ dropmsg = (msgqueue_t *) q_deqnext(&console_msgq);
+ if (dropmsg) KFREE(dropmsg);
+ }
+ }
+
+ /*
+ * Save text. If we run off the end of the buffer, prepare
+ * to allocate a new one
+ */
+ msg->data[msg->len++] = *buffer++;
+ length--;
+ if (msg->len == MSGQUEUESIZE) msg = NULL;
+ }
+}
+
+
+/* *********************************************************************
+ * console_readnum(num,ch)
+ *
+ * Read digits from the console until we get a non-digit. This
+ * is used to process escape sequences like ESC [ digits ~
+ *
+ * Input parameters:
+ * num - where to put returned number
+ * ch - pointer to character that starts sequence, returns
+ * character that terminated sequence
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void console_readnum(int *num,char *ch)
+{
+ int total = 0;
+
+ for (;;) {
+ total = (total * 10) + (*ch - '0');
+ while (console_read(ch,1) != 1) { POLL(); }
+ if (!((*ch >= '0') && (*ch <= '9'))) break;
+ }
+
+ *num = total;
+}
+
+
+/* *********************************************************************
+ * console_readkey(void)
+ *
+ * Very simple ANSI escape sequence parser, returns virtual
+ * key codes for function keys, arrows, etc.
+ *
+ * Hold your lunch, three levels of nested switch statements! :-)
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * virtual key code
+ ********************************************************************* */
+
+int console_readkey(void)
+{
+ unsigned char ch;
+ int num;
+
+ GETCHAR(ch);
+
+ switch (ch) {
+ case VKEY_ESC:
+ GETCHAR(ch);
+ switch (ch) {
+ case 'O':
+ GETCHAR(ch);
+ switch (ch) {
+ case 'P':
+ return VKEY_F1;
+ case 'Q':
+ return VKEY_F2;
+ case 'R':
+ return VKEY_F3;
+ case 'S':
+ return VKEY_F4;
+ }
+ return (int)ch;
+
+ case '[':
+ GETCHAR(ch);
+ if ((ch >= '0') && (ch <= '9')) {
+ console_readnum(&num,&ch);
+ if (ch == '~') {
+ switch (num) {
+ case 2:
+ return VKEY_HOME;
+ case 3:
+ return VKEY_PGUP;
+ case 5:
+ if (console_mode == XTERM) return VKEY_PGUP;
+ return VKEY_END;
+ case 6:
+ if (console_mode == XTERM) return VKEY_PGDN;
+ return VKEY_PGDN;
+ case 11:
+ return VKEY_F1;
+ case 12:
+ return VKEY_F2;
+ case 13:
+ return VKEY_F3;
+ case 14:
+ return VKEY_F4;
+ case 15:
+ return VKEY_F5;
+ case 17:
+ return VKEY_F6;
+ case 18:
+ return VKEY_F7;
+ case 19:
+ return VKEY_F8;
+ case 20:
+ return VKEY_F9;
+ case 21:
+ return VKEY_F10;
+ case 23:
+ return VKEY_F11;
+ case 24:
+ return VKEY_F12;
+ }
+ return (int)ch;
+ }
+ }
+ else {
+ switch (ch) {
+ case 'A':
+ return VKEY_UP;
+ case 'B':
+ return VKEY_DOWN;
+ case 'C':
+ return VKEY_RIGHT;
+ case 'D':
+ return VKEY_LEFT;
+ case 'F':
+ return VKEY_HOME;
+ case 'H':
+ return VKEY_END;
+ default:
+ return (int) ch;
+ }
+ }
+ default:
+ return (int)ch;
+
+ }
+ default:
+ return (int) ch;
+ }
+}
+
+
+/* *********************************************************************
+ * console_xxx(...)
+ *
+ * Various small routines to write out cursor control sequences.
+ *
+ * Input parameters:
+ * # of iterations, if necessary
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void console_backspace(int n)
+{
+ int t;
+
+ for (t = 0; t < n; t++) console_write("\b",1);
+}
+
+static void console_whiteout(int n)
+{
+ int t;
+
+ for (t = 0; t < n; t++) console_write(" ",1);
+ for (t = 0; t < n; t++) console_write("\b",1);
+}
+
+
+static void console_eraseeol(void)
+{
+ console_write("\033[K",3);
+}
+
+static void console_crlf(void)
+{
+ console_write("\r\n",2);
+}
+
+/* *********************************************************************
+ * console_readline(str,len)
+ *
+ * A simple 'gets' type routine for the console, with line
+ * editing support.
+ *
+ * Input parameters:
+ * prompt - prompt string
+ * str - pointer to user buffer
+ * len - length of user buffer
+ *
+ * Return value:
+ * number of characters read (terminating newline is not
+ * placed in the buffer)
+ ********************************************************************* */
+
+int console_readline(char *prompt,char *str,int maxlen)
+{
+ int reading = 1;
+ int ch;
+ int idx = 0;
+ int len = 0;
+ int t;
+ int klen;
+ int recall;
+ int nosave = 0;
+ char *x;
+ char env[10];
+
+ console_inreadline++;
+ recall = console_nextsave;
+
+ if (console_savedlines[console_nextsave]) {
+ KFREE(console_savedlines[console_nextsave]);
+ console_savedlines[console_nextsave] = NULL;
+ }
+ console_savedlines[console_nextsave] = strdup("");
+
+ if (prompt && *prompt) console_write(prompt,strlen(prompt));
+
+ POLL();
+ while (reading) {
+
+ /*
+ * If someone used console_log (above) or hit Control-C (below),
+ * redisplay the prompt and the string we've got so far.
+ */
+
+ if (console_redisplay) {
+ if (prompt && *prompt) console_write(prompt,strlen(prompt));
+ console_write(str,idx);
+ console_redisplay = 0;
+ continue;
+ }
+
+#if defined(CONFIG_MIPS_BRCM)
+
+ /*
+ * If a background process has set the global g_console_abort flag, stop
+ * reading from the keyboard.
+ */
+
+ if (g_console_abort) {
+ g_console_abort = 0;
+ break;
+ }
+
+#endif
+
+ /*
+ * if nobody's typed anything, keep polling
+ */
+
+ if (console_status() == 0) {
+ POLL();
+ continue;
+ }
+
+ /*
+ * Get the char from the keyboard
+ */
+
+ ch = console_readkey();
+ if (ch < 0) break;
+ if (ch == 0) continue;
+
+ /*
+ * And dispatch it. Lots of yucky character manipulation follows
+ */
+
+ switch (ch) {
+ case CTRL('C'): /* Ctrl-C - cancel line */
+ console_write("^C\r\n",4);
+ console_redisplay = 1;
+ nosave = 1;
+ idx = 0;
+ break;
+
+ case 0x7f: /* Backspace, Delete */
+ case CTRL('H'):
+ if (idx > 0) {
+ nosave = 0;
+ len--;
+ idx--;
+ console_write("\b",1);
+ if (len != idx) {
+ for (t = idx; t < len; t++) str[t] = str[t+1];
+ console_write(&str[idx],len-idx);
+ console_whiteout(1);
+ console_backspace(len-idx);
+ }
+ else {
+ console_whiteout(1);
+ }
+ }
+ break;
+
+ case CTRL('D'): /* Ctrl-D */
+ if ((idx >= 0) && (len != idx)) {
+ nosave = 0;
+ len--;
+ for (t = idx; t < len; t++) str[t] = str[t+1];
+ console_write(&str[idx],len-idx);
+ console_whiteout(1);
+ console_backspace(len-idx);
+ }
+ break;
+
+ case CTRL('B'): /* cursor left */
+ case VKEY_LEFT:
+ if (idx > 0) {
+ idx--;
+ console_backspace(1);
+ }
+ break;
+
+ case CTRL('F'): /* cursor right */
+ case VKEY_RIGHT:
+ if (idx < len) {
+ console_write(&str[idx],1);
+ idx++;
+ }
+ break;
+
+ case CTRL('A'): /* cursor to BOL */
+ console_backspace(idx);
+ idx = 0;
+ break;
+
+ case CTRL('E'): /* cursor to EOL */
+ if (len-idx > 0) console_write(&str[idx],len-idx);
+ idx = len;
+ break;
+
+ case CTRL('K'): /* Kill to EOL */
+ if (idx != len) {
+ str[len] = '\0';
+ if (console_killbuffer) KFREE(console_killbuffer);
+ console_killbuffer = strdup(&str[idx]);
+ console_whiteout(len-idx);
+ len = idx;
+ nosave = 0;
+ }
+ break;
+
+ case CTRL('Y'): /* Yank killed data */
+ if (console_killbuffer == NULL) break;
+ klen = strlen(console_killbuffer);
+ if (klen == 0) break;
+ if (len + klen > maxlen) break;
+ nosave = 0;
+ for (t = len + klen; t > idx; t--) {
+ str[t-1] = str[t-klen-1];
+ }
+ for (t = 0; t < klen; t++) str[t+idx] = console_killbuffer[t];
+ len += klen;
+ console_write(&str[idx],len-idx);
+ idx += klen;
+ console_backspace(len-idx-1);
+ break;
+
+ case CTRL('R'): /* Redisplay line */
+ str[len] = 0;
+ console_crlf();
+ console_write(prompt,strlen(prompt));
+ console_write(str,len);
+ console_backspace(len-idx);
+ break;
+
+ case CTRL('U'): /* Cancel line */
+ console_backspace(idx);
+ console_eraseeol();
+ if (len > 0) nosave = 1;
+ idx = 0;
+ len = 0;
+ break;
+
+ case CTRL('M'): /* terminate */
+ case CTRL('J'):
+ console_crlf();
+ reading = 0;
+ break;
+
+ case CTRL('P'):
+ case VKEY_UP: /* recall previous line */
+ t = recall;
+ t--;
+ if (t < 0) t = MAXSAVELINES-1;
+ if (console_savedlines[t] == NULL) break;
+ recall = t;
+ console_backspace(idx);
+ strcpy(str,console_savedlines[recall]);
+ len = idx = strlen(console_savedlines[recall]);
+ console_eraseeol();
+ console_write(str,len);
+ nosave = (t == ((console_nextsave - 1) % MAXSAVELINES));
+ break;
+
+ case CTRL('N'):
+ case VKEY_DOWN: /* Recall next line */
+ t = recall;
+ t++;
+ if (t == MAXSAVELINES) t = 0;
+ if (console_savedlines[t] == NULL) break;
+ recall = t;
+ console_backspace(idx);
+ strcpy(str,console_savedlines[recall]);
+ len = idx = strlen(console_savedlines[recall]);
+ console_eraseeol();
+ console_write(str,len);
+ nosave = 1;
+ break;
+
+ case VKEY_F1:
+ case VKEY_F2:
+ case VKEY_F3:
+ case VKEY_F4:
+ case VKEY_F5:
+ case VKEY_F6:
+ case VKEY_F7:
+ case VKEY_F8:
+ case VKEY_F9:
+ case VKEY_F10:
+ case VKEY_F11:
+ case VKEY_F12:
+ sprintf(env,"F%d",ch-VKEY_F1+1);
+ x = env_getenv(env);
+ if (x) {
+ console_backspace(idx);
+ strcpy(str,x);
+ idx = len = strlen(str);
+ console_eraseeol();
+ console_write(str,len);
+ console_crlf();
+ reading = 0;
+ nosave = 1;
+ }
+ /*
+ * If F12 is undefined, it means "repeat last command"
+ */
+ if (ch == VKEY_F12) {
+ t = recall;
+ t--;
+ if (t < 0) t = MAXSAVELINES-1;
+ if (console_savedlines[t] == NULL) break;
+ recall = t;
+ console_backspace(idx);
+ strcpy(str,console_savedlines[recall]);
+ len = idx = strlen(console_savedlines[recall]);
+ console_eraseeol();
+ console_write(str,len);
+ console_crlf();
+ reading = 0;
+ nosave = 1;
+ }
+ break;
+
+ default: /* insert character */
+ if (ch >= ' ') {
+ if (idx < (maxlen-1)) {
+ nosave = 0;
+ for (t = len; t > idx; t--) {
+ str[t] = str[t-1];
+ }
+ str[idx] = ch;
+ len++;
+ if (len != idx) {
+ console_write(&str[idx],len-idx);
+ console_backspace(len-idx-1);
+ }
+ idx++;
+ }
+ }
+ break;
+ }
+ }
+ POLL();
+
+ console_inreadline--;
+
+ str[len] = 0;
+
+ if ((len != 0) && !nosave) {
+ if (console_savedlines[console_nextsave]) {
+ KFREE(console_savedlines[console_nextsave]);
+ }
+ console_savedlines[console_nextsave] = strdup(str);
+ console_nextsave++;
+ if (console_nextsave == MAXSAVELINES) console_nextsave = 0;
+ }
+
+ return len;
+}
+
+#else /* CFG_MINIMAL_SIZE */
+/* *********************************************************************
+ * console_readline(str,len)
+ *
+ * A simple 'gets' type routine for the console,
+ * just calls the "noedit" variant for minimal code
+ * size builds.
+ *
+ * Input parameters:
+ * prompt - prompt string
+ * str - pointer to user buffer
+ * len - length of user buffer
+ *
+ * Return value:
+ * number of characters read (terminating newline is not
+ * placed in the buffer)
+ ********************************************************************* */
+
+int console_readline(char *prompt,char *str,int len)
+{
+ return console_readline_noedit(prompt,str,len);
+}
+
+#endif
diff --git a/cfe/cfe/main/cfe_devfuncs.c b/cfe/cfe/main/cfe_devfuncs.c
new file mode 100755
index 0000000..c3ab905
--- /dev/null
+++ b/cfe/cfe/main/cfe_devfuncs.c
@@ -0,0 +1,279 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Device Function stubs File: cfe_devfuncs.c
+ *
+ * This module contains device function stubs (small routines to
+ * call the standard "iocb" interface entry point to CFE).
+ * There should be one routine here per iocb function call.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+
+extern int cfe_iocb_dispatch(cfe_iocb_t *iocb);
+
+static int cfe_strlen(char *name)
+{
+ int count = 0;
+
+ while (*name) {
+ count++;
+ name++;
+ }
+
+ return count;
+}
+
+int cfe_open(char *name)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_DEV_OPEN;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = 0;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = sizeof(iocb_buffer_t);
+ iocb.plist.iocb_buffer.buf_offset = 0;
+ iocb.plist.iocb_buffer.buf_ptr = (unsigned char*)name;
+ iocb.plist.iocb_buffer.buf_length = cfe_strlen(name);
+
+ cfe_iocb_dispatch(&iocb);
+
+ return (iocb.iocb_status < 0) ? iocb.iocb_status : iocb.iocb_handle;
+}
+
+int cfe_close(int handle)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_DEV_CLOSE;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = handle;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = 0;
+
+ cfe_iocb_dispatch(&iocb);
+
+ return (iocb.iocb_status);
+
+}
+
+int cfe_readblk(int handle,cfe_offset_t offset,unsigned char *buffer,int length)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_DEV_READ;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = handle;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = sizeof(iocb_buffer_t);
+ iocb.plist.iocb_buffer.buf_offset = offset;
+ iocb.plist.iocb_buffer.buf_ptr = buffer;
+ iocb.plist.iocb_buffer.buf_length = length;
+
+ cfe_iocb_dispatch(&iocb);
+
+ return (iocb.iocb_status < 0) ? iocb.iocb_status : iocb.plist.iocb_buffer.buf_retlen;
+}
+
+int cfe_read(int handle,unsigned char *buffer,int length)
+{
+ return cfe_readblk(handle,0,buffer,length);
+}
+
+
+int cfe_writeblk(int handle,cfe_offset_t offset,unsigned char *buffer,int length)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_DEV_WRITE;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = handle;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = sizeof(iocb_buffer_t);
+ iocb.plist.iocb_buffer.buf_offset = offset;
+ iocb.plist.iocb_buffer.buf_ptr = buffer;
+ iocb.plist.iocb_buffer.buf_length = length;
+
+ cfe_iocb_dispatch(&iocb);
+
+ return (iocb.iocb_status < 0) ? iocb.iocb_status : iocb.plist.iocb_buffer.buf_retlen;
+}
+
+int cfe_write(int handle,unsigned char *buffer,int length)
+{
+ return cfe_writeblk(handle,0,buffer,length);
+}
+
+
+int cfe_ioctl(int handle,unsigned int ioctlnum,
+ unsigned char *buffer,int length,int *retlen,
+ cfe_offset_t offset)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_DEV_IOCTL;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = handle;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = sizeof(iocb_buffer_t);
+ iocb.plist.iocb_buffer.buf_offset = offset;
+ iocb.plist.iocb_buffer.buf_ioctlcmd = (cfe_offset_t) ioctlnum;
+ iocb.plist.iocb_buffer.buf_ptr = buffer;
+ iocb.plist.iocb_buffer.buf_length = length;
+
+ cfe_iocb_dispatch(&iocb);
+
+ if (retlen) *retlen = iocb.plist.iocb_buffer.buf_retlen;
+ return iocb.iocb_status;
+}
+
+int cfe_inpstat(int handle)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_DEV_INPSTAT;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = handle;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = sizeof(iocb_inpstat_t);
+ iocb.plist.iocb_inpstat.inp_status = 0;
+
+ cfe_iocb_dispatch(&iocb);
+
+ if (iocb.iocb_status < 0) return iocb.iocb_status;
+
+ return iocb.plist.iocb_inpstat.inp_status;
+
+}
+
+long long cfe_getticks(void)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_FW_GETTIME;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = 0;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = sizeof(iocb_time_t);
+ iocb.plist.iocb_time.ticks = 0;
+
+ cfe_iocb_dispatch(&iocb);
+
+ return iocb.plist.iocb_time.ticks;
+
+}
+
+int cfe_getenv(char *name,char *dest,int destlen)
+{
+ cfe_iocb_t iocb;
+
+ *dest = NULL;
+
+ iocb.iocb_fcode = CFE_CMD_ENV_GET;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = 0;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = sizeof(iocb_envbuf_t);
+ iocb.plist.iocb_envbuf.enum_idx = 0;
+ iocb.plist.iocb_envbuf.name_ptr = (unsigned char*)name;
+ iocb.plist.iocb_envbuf.name_length = strlen(name)+1;
+ iocb.plist.iocb_envbuf.val_ptr = (unsigned char*)dest;
+ iocb.plist.iocb_envbuf.val_length = destlen;
+
+ cfe_iocb_dispatch(&iocb);
+
+ return iocb.iocb_status;
+}
+
+int cfe_exit(int warm,int code)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_FW_RESTART;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = 0;
+ iocb.iocb_flags = warm ? CFE_FLG_WARMSTART : 0;
+ iocb.iocb_psize = sizeof(iocb_exitstat_t);
+ iocb.plist.iocb_exitstat.status = code;
+
+ cfe_iocb_dispatch(&iocb);
+
+ return (iocb.iocb_status);
+
+}
+
+int cfe_flushcache(int flg)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_FW_FLUSHCACHE;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = 0;
+ iocb.iocb_flags = flg;
+ iocb.iocb_psize = 0;
+
+ cfe_iocb_dispatch(&iocb);
+
+ return iocb.iocb_status;
+}
+
+int cfe_getdevinfo(char *name)
+{
+ cfe_iocb_t iocb;
+
+ iocb.iocb_fcode = CFE_CMD_DEV_GETINFO;
+ iocb.iocb_status = 0;
+ iocb.iocb_handle = 0;
+ iocb.iocb_flags = 0;
+ iocb.iocb_psize = sizeof(iocb_buffer_t);
+ iocb.plist.iocb_buffer.buf_offset = 0;
+ iocb.plist.iocb_buffer.buf_ptr = (unsigned char*)name;
+ iocb.plist.iocb_buffer.buf_length = cfe_strlen(name);
+
+ cfe_iocb_dispatch(&iocb);
+
+ return (iocb.iocb_status < 0) ? iocb.iocb_status : (int)iocb.plist.iocb_buffer.buf_devflags;
+}
diff --git a/cfe/cfe/main/cfe_error.c b/cfe/cfe/main/cfe_error.c
new file mode 100644
index 0000000..198e7a4
--- /dev/null
+++ b/cfe/cfe/main/cfe_error.c
@@ -0,0 +1,134 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Error strings File: cfe_error.h
+ *
+ * This file contains a mapping from error codes to strings
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "cfe.h"
+#include "cfe_error.h"
+
+/* *********************************************************************
+ * Types
+ ********************************************************************* */
+
+
+typedef struct errmap_s {
+ int errcode;
+ const char *string;
+} errmap_t;
+
+/* *********************************************************************
+ * Error code list
+ ********************************************************************* */
+
+errmap_t cfe_errorstrings[] = {
+ {CFE_OK ,"No error"},
+ {CFE_ERR ,"Error"},
+ {CFE_ERR_INV_COMMAND ,"Invalid command"},
+ {CFE_ERR_EOF ,"End of file reached"},
+ {CFE_ERR_IOERR ,"I/O error"},
+ {CFE_ERR_NOMEM ,"Insufficient memory"},
+ {CFE_ERR_DEVNOTFOUND ,"Device not found"},
+ {CFE_ERR_DEVOPEN ,"Device is open"},
+ {CFE_ERR_INV_PARAM ,"Invalid parameter"},
+ {CFE_ERR_ENVNOTFOUND ,"Environment variable not found"},
+ {CFE_ERR_ENVREADONLY ,"Environment variable is read-only"},
+ {CFE_ERR_NOTELF ,"Not an ELF-format executable"},
+ {CFE_ERR_NOT32BIT ,"Not a 32-bit executable"},
+ {CFE_ERR_WRONGENDIAN ,"Executable is wrong-endian"},
+ {CFE_ERR_BADELFVERS ,"Invalid ELF file version"},
+ {CFE_ERR_NOTMIPS ,"Not a MIPS ELF file"},
+ {CFE_ERR_BADELFFMT ,"Invalid ELF file"},
+ {CFE_ERR_BADADDR ,"Section would load outside available DRAM"},
+ {CFE_ERR_FILENOTFOUND ,"File not found"},
+ {CFE_ERR_UNSUPPORTED ,"Unsupported function"},
+ {CFE_ERR_HOSTUNKNOWN ,"Host name unknown"},
+ {CFE_ERR_TIMEOUT ,"Timeout occured"},
+ {CFE_ERR_PROTOCOLERR ,"Network protocol error"},
+ {CFE_ERR_NETDOWN ,"Network is down"},
+ {CFE_ERR_NONAMESERVER ,"No name server configured"},
+ {CFE_ERR_NOHANDLES ,"No more handles"},
+ {CFE_ERR_ALREADYBOUND ,"Already bound"},
+ {CFE_ERR_CANNOTSET ,"Cannot set network parameter"},
+ {CFE_ERR_NOMORE ,"No more enumerated items"},
+ {CFE_ERR_BADFILESYS ,"File system not recognized"},
+ {CFE_ERR_FSNOTAVAIL ,"File system not available"},
+ {CFE_ERR_INVBOOTBLOCK ,"Invalid boot block on disk"},
+ {CFE_ERR_WRONGDEVTYPE ,"Device type is incorrect for boot method"},
+ {CFE_ERR_BBCHECKSUM ,"Boot block checksum is invalid"},
+ {CFE_ERR_BOOTPROGCHKSUM ,"Boot program checksum is invalid"},
+ {CFE_ERR_LDRNOTAVAIL, "Loader is not available"},
+ {CFE_ERR_NOTREADY, "Device is not ready"},
+ {CFE_ERR_GETMEM, "Cannot get memory at specified address"},
+ {CFE_ERR_SETMEM, "Cannot set memory at specified address"},
+ {CFE_ERR_NOTCONN, "Socket is not connected"},
+ {CFE_ERR_ADDRINUSE, "Address is in use"},
+ {0,NULL}};
+
+
+/* *********************************************************************
+ * cfe_errortext(err)
+ *
+ * Returns the text corresponding to a CFE error code
+ *
+ * Input parameters:
+ * err - error code
+ *
+ * Return value:
+ * string description of error
+ ********************************************************************* */
+
+const char *cfe_errortext(int err)
+{
+ errmap_t *e = cfe_errorstrings;
+
+ while (e->string) {
+ if (e->errcode == err) return e->string;
+ e++;
+ }
+
+ return (const char *) "Unknown error";
+}
+
diff --git a/cfe/cfe/main/cfe_fatfs.c b/cfe/cfe/main/cfe_fatfs.c
new file mode 100644
index 0000000..f2fa49f
--- /dev/null
+++ b/cfe/cfe/main/cfe_fatfs.c
@@ -0,0 +1,1983 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * FAT file system File: cfe_fatfs.c
+ *
+ * This module knows how to read files from a FAT formatted
+ * file system (12 or 16 bit fats only for now)
+ *
+ * Eventually, we'll also include support for the FAT Translation
+ * Layer (FTL) on PCMCIA flash file systems.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_error.h"
+#include "cfe_fileops.h"
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+
+#include "cfe_loader.h"
+
+#include "cfe.h"
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define SECTORSIZE 512
+#define DIRENTRYSIZE 32
+#define DIRPERSECTOR (SECTORSIZE/DIRENTRYSIZE)
+
+/*#define _FATFS_DEBUG_*/
+
+/*
+ * Bios Parameter Block offsets and values
+ */
+
+#define BPB_JMPINSTR 0x00
+#define BPB_JMPINSTR_VALUE 0xEB
+#define BPB_JMPINSTR_VALUE2 0xE9
+#define BPB_SEAL 0x1FE
+#define BPB_SEAL_VALUE 0xAA55
+
+#define BPB_BYTESPERSECTOR 0x0B
+#define BPB_SECTORSPERCLUSTER 0x0D
+#define BPB_RESERVEDSECTORS 0x0E
+#define BPB_NUMFATS 0x10
+#define BPB_MAXROOTDIR 0x11
+#define BPB_TOTALSECTORS 0x13
+#define BPB_SECTORSPERFAT 0x16
+#define BPB_SECTORSPERTRACK 0x18
+#define BPB_NUMHEADS 0x1A
+#define BPB_HIDDENSECTORS 0x1C
+#define BPB_SYSTEMID 54
+#define BPB_MEDIADESCRIPTOR 21
+#define BPB_SIGNATURE 38
+#define BPB_SIGNATURE_VALUE1 0x28
+#define BPB_SIGNATURE_VALUE2 0x29
+
+/*
+ * Partition types
+ */
+
+#define PARTTYPE_EMPTY 0
+#define PARTTYPE_FAT12 1
+#define PARTTYPE_FAT16 4
+#define PARTTYPE_FAT16BIG 6
+#define PARTTYPE_FAT32 0x0B
+
+/*
+ * Partition table offsets
+ */
+#define PTABLE_STATUS 0
+#define PTABLE_STARTHEAD 1
+#define PTABLE_STARTSECCYL 2 /* 2 bytes */
+#define PTABLE_TYPE 4
+#define PTABLE_ENDHEAD 5
+#define PTABLE_ENDSECCYL 6 /* 2 bytes */
+#define PTABLE_BOOTSECTOR 8 /* 4 bytes */
+#define PTABLE_NUMSECTORS 12 /* 4 bytes */
+
+#define PTABLE_SIZE 16
+#define PTABLE_COUNT 4
+#define PTABLE_OFFSET (512-2-(PTABLE_COUNT*PTABLE_SIZE))
+
+#define PTABLE_STATUS_ACTIVE 0x80
+
+/*
+ * Directory attributes
+ */
+
+#define ATTRIB_NORMAL 0x00
+#define ATTRIB_READONLY 0x01
+#define ATTRIB_HIDDEN 0x02
+#define ATTRIB_SYSTEM 0x04
+#define ATTRIB_LABEL 0x08
+#define ATTRIB_DIR 0x10
+#define ATTRIB_ARCHIVE 0x20
+
+#define ATTRIB_LFN 0x0F
+
+/*
+ * Macros to read fields in directory & BPB entries
+ */
+
+#define READWORD(buffer,x) (((unsigned int) (buffer)[(x)]) | \
+ (((unsigned int) (buffer)[(x)+1]) << 8))
+
+#define READWORD32(buffer,x) (READWORD(buffer,(x)) | (READWORD(buffer,(x)+2) << 16))
+
+#define READBYTE(buffer,x) ((unsigned int) (buffer)[(x)])
+
+/*
+ * Directory entry offsets and values
+ */
+
+#define DIR_CHECKSUM 13
+#define DIR_FILELENGTH 28
+#define DIR_STARTCLUSTER 26
+#define DIR_ATTRIB 11
+#define DIR_NAMEOFFSET 0
+#define DIR_NAMELEN 8
+#define DIR_EXTOFFSET 8
+#define DIR_EXTLEN 3
+
+#define DIRENTRY_CHECKSUM(e) READBYTE(e,DIR_CHECKSUM)
+#define DIRENTRY_FILELENGTH(e) READWORD32(e,DIR_FILELENGTH)
+#define DIRENTRY_STARTCLUSTER(e) READWORD(e,DIR_STARTCLUSTER)
+#define DIRENTRY_ATTRIB(e) READBYTE(e,DIR_ATTRIB)
+
+#define DIRENTRY_LAST 0
+#define DIRENTRY_DELETED 0xE5
+#define DIRENTRY_PARENTDIR 0x2E
+
+#define DIRENTRY_LFNIDX(e) READBYTE(e,0)
+#define LFNIDX_MASK 0x1F
+#define LFNIDX_END 0x40
+#define LFNIDX_MAX 20
+
+/* *********************************************************************
+ * Types
+ ********************************************************************* */
+
+/*
+ * Internalized BPB
+ */
+
+typedef struct bpb_s {
+ unsigned int bpb_bytespersector;
+ unsigned int bpb_sectorspercluster;
+ unsigned int bpb_reservedsectors;
+ unsigned int bpb_numfats;
+ unsigned int bpb_maxrootdir;
+ unsigned int bpb_totalsectors;
+ unsigned int bpb_sectorsperfat;
+ unsigned int bpb_sectorspertrack;
+ unsigned int bpb_numheads;
+ unsigned int bpb_hiddensectors;
+} bpb_t;
+
+/*
+ * FAT Filesystem descriptor - contains working information
+ * about an "open" file system
+ */
+
+typedef struct fatfs_s {
+ int fat_fh;
+ int fat_refcnt;
+ bpb_t fat_bpb;
+ int fat_twelvebit;
+ int fat_partstart;
+ uint8_t fat_dirsector[SECTORSIZE];
+ int fat_dirsecnum;
+ uint8_t fat_fatsector[SECTORSIZE];
+ int fat_fatsecnum;
+} fatfs_t;
+
+/*
+ * FAT Chain - describes a series of FAT entries
+ */
+
+typedef struct fatchain_s {
+ int fat_start;
+ uint16_t *fat_entries;
+ int fat_count;
+} fatchain_t;
+
+/*
+ * FAT File descriptor - contains working information
+ * about an open file (including the filesystem info)
+ */
+
+typedef struct fatfile_s {
+ fatfs_t *ff_fat;
+ int ff_filelength;
+ fatchain_t ff_chain;
+ int ff_curpos;
+ int ff_cursector;
+ uint8_t ff_sector[SECTORSIZE];
+} fatfile_t;
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+static int fatfs_fileop_xinit(void **fsctx,void *filename);
+static int fatfs_fileop_pinit(void **fsctx,void *filename);
+static int fatfs_fileop_open(void **ref,void *fsctx,char *filename,int mode);
+static int fatfs_fileop_read(void *ref,uint8_t *buf,int len);
+static int fatfs_fileop_write(void *ref,uint8_t *buf,int len);
+static int fatfs_fileop_seek(void *ref,int offset,int how);
+static void fatfs_fileop_close(void *ref);
+static void fatfs_fileop_uninit(void *fsctx);
+
+static int fatfs_check_for_partition_table(fatfs_t *fatfs);
+
+/* *********************************************************************
+ * FAT fileio dispatch table
+ ********************************************************************* */
+
+/*
+ * Raw FAT (no partition table) - used only on floppies
+ */
+
+const fileio_dispatch_t fatfs_fileops = {
+ "rfat",
+ LOADFLG_NOBB,
+ fatfs_fileop_xinit,
+ fatfs_fileop_open,
+ fatfs_fileop_read,
+ fatfs_fileop_write,
+ fatfs_fileop_seek,
+ fatfs_fileop_close,
+ fatfs_fileop_uninit
+};
+
+/*
+ * Partitioned FAT - used on Zip disks, removable hard disks,
+ * hard disks, flash cards, etc.
+ */
+
+const fileio_dispatch_t pfatfs_fileops = {
+ "fat",
+ LOADFLG_NOBB,
+ fatfs_fileop_pinit,
+ fatfs_fileop_open,
+ fatfs_fileop_read,
+ fatfs_fileop_write,
+ fatfs_fileop_seek,
+ fatfs_fileop_close,
+ fatfs_fileop_uninit
+};
+
+
+/* *********************************************************************
+ * fat_readsector(fatfs,sector,numsec,buffer)
+ *
+ * Read one or more sectors from the disk into memory
+ *
+ * Input parameters:
+ * fatfs - fat filesystem descriptor
+ * sector - sector number
+ * numsec - number of sectors to read
+ * buffer - buffer to read sectors into
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int fat_readsector(fatfs_t *fatfs,int sector,int numsec,uint8_t *buffer)
+{
+ int res;
+
+ res = cfe_readblk(fatfs->fat_fh,(sector+fatfs->fat_partstart)*SECTORSIZE,
+ buffer,numsec*SECTORSIZE);
+
+ if (res != numsec*SECTORSIZE) return CFE_ERR_IOERR;
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * fat_dumpbpb(bpb)
+ *
+ * Debug function; display fields in a BPB
+ *
+ * Input parameters:
+ * bpb - BIOS parameter block structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+#ifdef _FATFS_DEBUG_
+static void fat_dumpbpb(bpb_t *bpb)
+{
+ xprintf("Bytes per sector %d\n",bpb->bpb_bytespersector);
+ xprintf("Sectors per cluster %d\n",bpb->bpb_sectorspercluster);
+ xprintf("Reserved sectors %d\n",bpb->bpb_reservedsectors);
+ xprintf("Number of FATs %d\n",bpb->bpb_numfats);
+ xprintf("Root dir entries %d\n",bpb->bpb_maxrootdir);
+ xprintf("Total sectors %d\n",bpb->bpb_totalsectors);
+ xprintf("Sectors per FAT %d\n",bpb->bpb_sectorsperfat);
+ xprintf("Sectors per track %d\n",bpb->bpb_sectorspertrack);
+ xprintf("Number of heads %d\n",bpb->bpb_numheads);
+ xprintf("Hidden sectors %d\n",bpb->bpb_hiddensectors);
+}
+#endif
+
+/* *********************************************************************
+ * fat_findpart(fatfs)
+ *
+ * For partitioned disks, locate the active partition
+ * and set "fat_partstart" accordingly
+ *
+ * Input parameters:
+ * fatfs - FAT filesystem descriptor
+ *
+ * Return value:
+ * 0 if we found a valid partition table; else error code
+ ********************************************************************* */
+
+static int fat_findpart(fatfs_t *fatfs)
+{
+ uint8_t buffer[SECTORSIZE];
+ uint8_t *part;
+ int res;
+ int idx;
+
+ fatfs->fat_partstart = 0; /* make sure we get real boot sector */
+ res = fat_readsector(fatfs,0,1,buffer);
+ if (res < 0) return res;
+
+ /*
+ * Normally you're supposed to check for a JMP instruction.
+ * At least that's what many people do. Flash MBRs don't start
+ * with JMP instructions, so just look for the seal.
+ *
+ *
+ * if (READBYTE(buffer,BPB_JMPINSTR) != BPB_JMPINSTR_VALUE) {
+ * return CFE_ERR_BADFILESYS;
+ * }
+ */
+
+ /*
+ * Check the seal at the end of th sector
+ */
+
+ if (READWORD(buffer,BPB_SEAL) != BPB_SEAL_VALUE) return CFE_ERR_BADFILESYS;
+
+ /*
+ * Look for an active FAT partition. The partition we want must
+ * be the active one. We do not deal with extended partitions
+ * here. Hey, this is supposed to be boot code!
+ */
+
+ part = &buffer[PTABLE_OFFSET];
+ for (idx = 0; idx < PTABLE_COUNT; idx++) {
+ if ((part[PTABLE_STATUS] == PTABLE_STATUS_ACTIVE) &&
+ ((part[PTABLE_TYPE] == PARTTYPE_FAT12) ||
+ (part[PTABLE_TYPE] == PARTTYPE_FAT16) ||
+ (part[PTABLE_TYPE] == PARTTYPE_FAT16BIG))) {
+ break;
+ }
+
+ part += PTABLE_SIZE;
+ }
+
+ if (idx == PTABLE_COUNT) return CFE_ERR_BADFILESYS;
+
+ /*
+ * The info we want is really just the pointer to the
+ * boot (BPB) sector. Get that and we'll use it for an
+ * offset into the disk later.
+ */
+
+ fatfs->fat_partstart = READWORD32(part,PTABLE_BOOTSECTOR);
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * fat_readbpb(fatfs)
+ *
+ * Read and internalize the BIOS Parameter Block
+ *
+ * Input parameters:
+ * fatfs - FAT filesystem descriptor
+ *
+ * Return value:
+ * 0 if ok
+ * else error code (usually, BPB is not valid)
+ ********************************************************************* */
+
+static int fat_readbpb(fatfs_t *fatfs)
+{
+ uint8_t buffer[SECTORSIZE];
+ int res;
+
+ res = fat_readsector(fatfs,0,1,buffer);
+ if (res < 0) return res;
+
+ if (READBYTE(buffer,BPB_JMPINSTR) != BPB_JMPINSTR_VALUE) return CFE_ERR_BADFILESYS;
+ if (READWORD(buffer,BPB_SEAL) != BPB_SEAL_VALUE) return CFE_ERR_BADFILESYS;
+
+ fatfs->fat_bpb.bpb_bytespersector = READWORD(buffer,BPB_BYTESPERSECTOR);
+ fatfs->fat_bpb.bpb_sectorspercluster = READBYTE(buffer,BPB_SECTORSPERCLUSTER);
+ fatfs->fat_bpb.bpb_reservedsectors = READWORD(buffer,BPB_RESERVEDSECTORS);
+ fatfs->fat_bpb.bpb_numfats = READBYTE(buffer,BPB_NUMFATS);
+ fatfs->fat_bpb.bpb_maxrootdir = READWORD(buffer,BPB_MAXROOTDIR);
+ fatfs->fat_bpb.bpb_totalsectors = READWORD(buffer,BPB_TOTALSECTORS);
+ fatfs->fat_bpb.bpb_sectorsperfat = READWORD(buffer,BPB_SECTORSPERFAT);
+ fatfs->fat_bpb.bpb_sectorspertrack = READWORD(buffer,BPB_SECTORSPERTRACK);
+ fatfs->fat_bpb.bpb_numheads = READWORD(buffer,BPB_NUMHEADS);
+ fatfs->fat_bpb.bpb_hiddensectors = READWORD(buffer,BPB_HIDDENSECTORS);
+
+ fatfs->fat_twelvebit = 1;
+ if (memcmp(&buffer[0x36],"FAT16 ",8) == 0) fatfs->fat_twelvebit = 0;
+
+ if (fatfs->fat_bpb.bpb_bytespersector != SECTORSIZE) return CFE_ERR_BADFILESYS;
+ if (fatfs->fat_bpb.bpb_numfats > 2) return CFE_ERR_BADFILESYS;
+
+ /*
+ * XXX sanity check other fields
+ */
+
+#ifdef _FATFS_DEBUG_
+ fat_dumpbpb(&(fatfs->fat_bpb));
+#endif
+
+ return 0;
+}
+
+
+
+/* *********************************************************************
+ * fat_getentry(fatfs,entry)
+ *
+ * Read a FAT entry. This is more involved than you'd think,
+ * since we have to deal with 12 and 16 (and someday 32) bit FATs,
+ * and the nasty case where a 12-bit FAT entry crosses a sector
+ * boundary.
+ *
+ * Input parameters:
+ * fatfs - FAT filesystem descriptor
+ * entry - index of FAT entry
+ *
+ * Return value:
+ * FAT entry, or <0 if an error occured
+ ********************************************************************* */
+
+static int fat_getfatentry(fatfs_t *fatfs,int entry)
+{
+ int fatsect;
+ int byteoffset;
+ int fatstart;
+ int fatoffset;
+ uint8_t b1,b2,b3;
+ int res;
+
+ fatstart = fatfs->fat_bpb.bpb_reservedsectors;
+
+ if (fatfs->fat_twelvebit) {
+ int odd;
+ odd = entry & 1;
+ byteoffset = ((entry & ~1) * 3) / 2;
+ fatsect = byteoffset / SECTORSIZE;
+ fatoffset = byteoffset % SECTORSIZE;
+
+ if (fatfs->fat_fatsecnum != fatsect) {
+ res = fat_readsector(fatfs,fatsect+fatstart,1,fatfs->fat_fatsector);
+ if (res < 0) {
+ return res;
+ }
+ fatfs->fat_fatsecnum = fatsect;
+ }
+
+ b1 = fatfs->fat_fatsector[fatoffset];
+
+ if ((fatoffset+1) >= SECTORSIZE) {
+ res = fat_readsector(fatfs,fatsect+1+fatstart,1,fatfs->fat_fatsector);
+ if (res < 0) {
+ return res;
+ }
+ fatfs->fat_fatsecnum = fatsect+1;
+ fatoffset -= SECTORSIZE;
+ }
+
+ b2 = fatfs->fat_fatsector[fatoffset+1];
+
+ if ((fatoffset+2) >= SECTORSIZE) {
+ res = fat_readsector(fatfs,fatsect+1+fatstart,1,fatfs->fat_fatsector);
+ if (res < 0) {
+ return res;
+ }
+ fatfs->fat_fatsecnum = fatsect+1;
+ fatoffset -= SECTORSIZE;
+ }
+
+ b3 = fatfs->fat_fatsector[fatoffset+2];
+
+ if (odd) {
+ return ((unsigned int) b3 << 4) + ((unsigned int) (b2 & 0xF0) >> 4);
+ }
+ else {
+ return ((unsigned int) (b2 & 0x0F) << 8) + ((unsigned int) b1);
+ }
+
+ }
+ else {
+ byteoffset = entry * 2;
+ fatsect = byteoffset / SECTORSIZE;
+ fatoffset = byteoffset % SECTORSIZE;
+
+ if (fatfs->fat_fatsecnum != fatsect) {
+ res = fat_readsector(fatfs,fatsect+fatstart,1,fatfs->fat_fatsector);
+ if (res < 0) {
+ return res;
+ }
+ fatfs->fat_fatsecnum = fatsect;
+ }
+
+ b1 = fatfs->fat_fatsector[fatoffset];
+ b2 = fatfs->fat_fatsector[fatoffset+1];
+ return ((unsigned int) b1) + (((unsigned int) b2) << 8);
+ }
+}
+
+/* *********************************************************************
+ * fat_getrootdirentry(fatfs,entryidx,entry)
+ *
+ * Read a root directory entry. The FAT12/16 root directory
+ * is a contiguous group of sectors, whose size is specified in
+ * the BPB. This routine just digs out an entry from there
+ *
+ * Input parameters:
+ * fatfs - FAT filesystem descriptor
+ * entryidx - 0-based entry index to read
+ * entry - pointer to directory entry (32 bytes)
+ *
+ * Return value:
+ * 0 if ok
+ * <0 if error occured
+ ********************************************************************* */
+
+static int fat_getrootdirentry(fatfs_t *fatfs,int entryidx,uint8_t *entry)
+{
+ int rootdirstart;
+ int rootdirsize;
+ int dirsecnum;
+ int res;
+
+ if (entryidx >= fatfs->fat_bpb.bpb_maxrootdir) {
+ memset(entry,0,DIRENTRYSIZE);
+ return CFE_ERR_INV_PARAM;
+ }
+
+ rootdirstart = fatfs->fat_bpb.bpb_reservedsectors +
+ fatfs->fat_bpb.bpb_numfats * fatfs->fat_bpb.bpb_sectorsperfat;
+
+ rootdirsize = fatfs->fat_bpb.bpb_maxrootdir / DIRENTRYSIZE;
+
+ dirsecnum = rootdirstart + entryidx / DIRPERSECTOR;
+
+ if (fatfs->fat_dirsecnum != dirsecnum) {
+ res = fat_readsector(fatfs,dirsecnum,1,fatfs->fat_dirsector);
+ if (res < 0) {
+ return res;
+ }
+ fatfs->fat_dirsecnum = dirsecnum;
+ }
+
+ memcpy(entry,&(fatfs->fat_dirsector[(entryidx % DIRPERSECTOR)*DIRENTRYSIZE]),
+ DIRENTRYSIZE);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * fat_checksumname(name)
+ *
+ * Calculate the "long filename" checksum for a given short name.
+ * All LFN directory entries associated with the short name are
+ * given the same checksum byte, to help keep the long name
+ * consistent.
+ *
+ * Input parameters:
+ * name - pointer to 32-byte directory entry
+ *
+ * Return value:
+ * checksum value
+ ********************************************************************* */
+
+static uint8_t fat_checksumname(uint8_t *name)
+{
+ uint8_t sum = 0;
+ uint8_t newbit;
+ int idx;
+
+ for (idx = 0; idx < 11; idx++) {
+ newbit = (sum & 1) ? 0x80 : 0x00;
+ sum >>= 1;
+ sum |= newbit;
+ sum += name[idx];
+ }
+
+ return sum;
+}
+
+#ifdef _FATFS_DEBUG_
+void fat_dumpdirentry(uint8_t *entry);
+void fat_dumpdirentry(uint8_t *entry)
+{
+ uint8_t name[32];
+ int idx;
+
+ if (entry[11] != ATTRIB_LFN) {
+ memcpy(name,entry,11);
+ name[11] = 0;
+ xprintf("%s %02X %04X %d\n",
+ name,DIRENTRY_ATTRIB(entry),
+ DIRENTRY_STARTCLUSTER(entry),
+ DIRENTRY_FILELENGTH(entry));
+ }
+ else {
+ for (idx = 0; idx < 5; idx++) {
+ name[idx] = entry[(idx*2)+1];
+ }
+ for (idx = 0; idx < 6; idx++) {
+ name[idx+5] = entry[(idx*2)+14];
+ }
+ for (idx = 0; idx < 2; idx++) {
+ name[idx+11] = entry[(idx*2)+28];
+ }
+ name[13] = '\0';
+ xprintf("%02X: %s %04X cksum %02X\n",entry[0],
+ name,READWORD(entry,0x1A),entry[13]);
+ }
+}
+#endif
+
+
+/* *********************************************************************
+ * fat_walkfatchain(fat,start,arg,func)
+ *
+ * Walk a FAT chain, calling a callback routine for each entry
+ * we find along the way.
+ *
+ * Input parameters:
+ * fat - FAT filesystem descriptor
+ * start - starting FAT entry (from the directory, usually)
+ * arg - argument to pass to callback routine
+ * func - function to call for each FAT entry
+ *
+ * Return value:
+ * 0 if all elements processed
+ * <0 if error occured
+ * >0 if callback routine returned a nonzero value
+ ********************************************************************* */
+
+static int fat_walkfatchain(fatfs_t *fat,int start,
+ void *arg,
+ int (*func)(fatfs_t *fat,
+ int e,
+ int prev_e,
+ void *arg))
+{
+ int prev_e = 0;
+ int ending_e;
+ int e;
+ int res = 0;
+
+ e = start;
+
+ /* Note: ending FAT entry can be 0x(F)FF8..0x(F)FFF. We assume that the
+ 'getfatentry' call won't return values above that. */
+ if (fat->fat_twelvebit) {
+ ending_e = 0xFF8;
+ }
+ else {
+ ending_e = 0xFFF8;
+ }
+
+ while (e < ending_e) {
+ res = (*func)(fat,e,prev_e,arg);
+ if (res) break;
+ prev_e = e;
+ e = fat_getfatentry(fat,e);
+ if (e < 0) return e;
+ }
+
+ return res;
+}
+
+/* *********************************************************************
+ * fat_getwalkfunc(fat,e,prev_e,arg)
+ *
+ * Callback routien to collect all of the FAT entries into
+ * a FAT chain descriptor
+ *
+ * Input parameters:
+ * fat - FAT filesystem descriptor
+ * e - current entry
+ * prev_e - previous entry (0 if first entry)
+ * arg - argument passed to fat_walkfatchain
+ *
+ * Return value:
+ * 0 to keep walking
+ * else value to return from fat_walkfatchain
+ ********************************************************************* */
+
+static int fat_getwalkfunc(fatfs_t *fat,int e,
+ int prev_e,void *arg)
+{
+ fatchain_t *chain = arg;
+
+ if (chain->fat_entries) {
+ chain->fat_entries[chain->fat_count] = (uint16_t) e;
+ }
+
+ chain->fat_count++;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * fat_getchain(fat,start,chain)
+ *
+ * Walk an entire FAT chain and remember the chain in a
+ * FAT chain descriptor
+ *
+ * Input parameters:
+ * fat - FAT filesystem descriptor
+ * start - starting FAT entry
+ * chain - chain descriptor
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int fat_getchain(fatfs_t *fat,int start,fatchain_t *chain)
+{
+ int res;
+
+ chain->fat_entries = NULL;
+ chain->fat_count = 0;
+ chain->fat_start = start;
+
+ /*
+ * walk once to count the entries.
+ *
+ * For regular files, you probably don't have to do this
+ * since you can predict exactly how many FAT entries
+ * there are given the file length.
+ */
+
+ res = fat_walkfatchain(fat,start,chain,fat_getwalkfunc);
+ if (res < 0) return res;
+
+ /*
+ * allocate space for the entries. Include one extra
+ * slot for the first entry, since the first entry
+ * does not actually appear in the FAT (the fat is
+ * only the 'next' pointers).
+ */
+
+ if (chain->fat_count == 0) return 0;
+ chain->fat_entries = KMALLOC((chain->fat_count+1)*sizeof(uint16_t),0);
+ chain->fat_count = 0;
+
+ /*
+ * walk again to collect entries
+ */
+ res = fat_walkfatchain(fat,start,chain,fat_getwalkfunc);
+ if (res < 0) return res;
+
+ return chain->fat_count;
+}
+
+
+/* *********************************************************************
+ * fat_freechain(chain)
+ *
+ * Free memory associated with a FAT chain
+ *
+ * Input parameters:
+ * chain - chain descriptor
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void fat_freechain(fatchain_t *chain)
+{
+ if (chain->fat_entries) {
+ KFREE(chain->fat_entries);
+ chain->fat_entries = NULL;
+ }
+ chain->fat_count = 0;
+}
+
+/* *********************************************************************
+ * fat_clusteridx(fat,chain,idx)
+ *
+ * Index into a FAT chain and return the nth cluster number
+ * from the chain
+ *
+ * Input parameters:
+ * fat - fat filesystem descriptor
+ * chain - chain descriptor
+ * idx - index into FAT chain
+ *
+ * Return value:
+ * FAT entry at the nth index, or
+ * <0 if an error occured
+ ********************************************************************* */
+static int fat_clusteridx(fatfs_t *fat,fatchain_t *chain,int idx)
+{
+ if (idx >= chain->fat_count) return CFE_ERR_INV_PARAM; /* error! */
+ return (int) (unsigned int) chain->fat_entries[idx];
+}
+
+/* *********************************************************************
+ * fat_sectoridx(fat,chain,idx)
+ *
+ * Return the sector nunber of the nth sector in a given
+ * FAT chain. This routine knows how to translate cluster
+ * numbers into sector numbers.
+ *
+ * Input parameters:
+ * fat - FAT filesystem descriptor
+ * chain - FAT chain
+ * idx - index of which sector to find
+ *
+ * Return value:
+ * sector number
+ * <0 if an error occured
+ ********************************************************************* */
+static int fat_sectoridx(fatfs_t *fat,fatchain_t *chain,int idx)
+{
+ int clusteridx;
+ int sectoridx;
+ int sector;
+ int fatentry;
+
+ clusteridx = idx / fat->fat_bpb.bpb_sectorspercluster;
+ sectoridx = idx % fat->fat_bpb.bpb_sectorspercluster;
+
+ fatentry = fat_clusteridx(fat,chain,clusteridx);
+
+ if (fatentry < 0) xprintf("ran off end of fat chain!\n");
+ if (fatentry < 2) xprintf("fat entries should be >= 2\n");
+
+ sector = fat->fat_bpb.bpb_reservedsectors +
+ (fat->fat_bpb.bpb_maxrootdir * DIRENTRYSIZE)/SECTORSIZE +
+ (fat->fat_bpb.bpb_numfats * fat->fat_bpb.bpb_sectorsperfat) +
+ (fatentry - 2) * fat->fat_bpb.bpb_sectorspercluster +
+ sectoridx;
+
+ return sector;
+}
+
+/* *********************************************************************
+ * fat_getsubdirentry(fat,chain,idx,direntry)
+ *
+ * This routine is similar to fat_getrootdirentry except it
+ * works on a subdirectory. FAT subdirectories are like files
+ * containing directory entries, so we use the "get nth sector
+ * in chain" routines to walk the chains of sectors reading directory
+ * entries.
+ *
+ * Input parameters:
+ * fat - FAT filesystem descriptor
+ * chain - FAT chain
+ * idx - index of entry to read
+ * direntry - place to put directory entry we read
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int fat_getsubdirentry(fatfs_t *fat,fatchain_t *chain,
+ int idx,uint8_t *direntry)
+{
+ int sector;
+ int res;
+
+ sector = fat_sectoridx(fat,chain,idx/DIRPERSECTOR);
+
+ if (sector < 0) return sector;
+
+ if (fat->fat_dirsecnum != sector) {
+ res = fat_readsector(fat,sector,1,fat->fat_dirsector);
+ if (res < 0) {
+ return res;
+ }
+ fat->fat_dirsecnum = sector;
+ }
+
+ memcpy(direntry,&(fat->fat_dirsector[(idx % DIRPERSECTOR)*DIRENTRYSIZE]),
+ DIRENTRYSIZE);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * fat_getshortname(direntry,name)
+ *
+ * Read the short filename from a directory entry, converting
+ * it into its classic 8.3 form
+ *
+ * Input parameters:
+ * direntry - directory entry
+ * name - place to put 8.3 name
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void fat_getshortname(uint8_t *direntry,char *name)
+{
+ int idx;
+
+ /*
+ * Collect the base file name
+ */
+
+ for (idx = DIR_NAMEOFFSET; idx < (DIR_NAMEOFFSET+DIR_NAMELEN); idx++) {
+ if (direntry[idx] == ' ') break;
+ *name++ = direntry[idx];
+ }
+
+ /*
+ * Put in the dot for the extension only if there
+ * is an extension.
+ */
+
+ if (direntry[DIR_EXTOFFSET] != ' ') *name++ = '.';
+
+ /*
+ * Collect the extension
+ */
+
+ for (idx = DIR_EXTOFFSET; idx < (DIR_EXTOFFSET+DIR_EXTLEN); idx++) {
+ if (direntry[idx] == ' ') break;
+ *name++ = direntry[idx];
+ }
+
+ *name = '\0';
+}
+
+
+/* *********************************************************************
+ * fat_getlongname(fat,chain,diridx,shortentry,longname)
+ *
+ * Look backwards in the directory to locate the long file name
+ * that corresponds to the short file name passed in 'shortentry'
+ *
+ * Input parameters:
+ * fat - FAT filesystem descriptor
+ * chain - chain describing current directory, or NULL
+ * if the current directory is the root directory
+ * diridx - index of the short file name
+ * shortentry - points to the short directory entry
+ * longname - buffer to receive long file name (up to 261 chars)
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int fat_getlongname(fatfs_t *fat,fatchain_t *chain,int diridx,
+ uint8_t *shortentry,char *longname)
+{
+ int lfnidx = 1;
+ uint8_t checksum;
+ uint8_t direntry[DIRENTRYSIZE];
+ int idx;
+ char *lfnptr;
+ int badlfn = 0;
+
+ *longname = '\0';
+
+ /*
+ * idx is the entry # of the short name
+ */
+
+ checksum = fat_checksumname(shortentry);
+
+ /*
+ * Start working backwards from current entry
+ * and collect pieces of the lfn
+ */
+
+ lfnptr = longname;
+ diridx--;
+
+ while (diridx > 0) {
+
+ /*
+ * Read previous entry
+ */
+
+ if (chain) {
+ fat_getsubdirentry(fat,chain,diridx,direntry);
+ }
+ else {
+ fat_getrootdirentry(fat,diridx,direntry);
+ }
+
+ /*
+ * Checksum must match, it must have the right entry index,
+ * and it must have the LFN attribute
+ */
+
+ if (DIRENTRY_CHECKSUM(direntry) != checksum) {
+ badlfn = 1;
+ break;
+ }
+ if ((DIRENTRY_LFNIDX(direntry) & LFNIDX_MASK) != lfnidx) {
+ badlfn = 1;
+ break;
+ }
+
+ if (DIRENTRY_ATTRIB(direntry) != ATTRIB_LFN) {
+ badlfn = 1;
+ break;
+ }
+
+ /*
+ * Collect the chars from the filename. Note we
+ * don't deal well with real unicode chars here.
+ */
+
+ for (idx = 0; idx < 5; idx++) {
+ *lfnptr++ = direntry[(idx*2)+1];
+ }
+ for (idx = 0; idx < 6; idx++) {
+ *lfnptr++ = direntry[(idx*2)+14];
+ }
+ for (idx = 0; idx < 2; idx++) {
+ *lfnptr++ = direntry[(idx*2)+28];
+ }
+
+ /*
+ * Don't go too far
+ */
+
+ if (DIRENTRY_LFNIDX(direntry) & LFNIDX_END) break;
+ lfnidx++;
+ if (lfnidx > LFNIDX_MAX) {
+ badlfn = 1;
+ break;
+ }
+
+ diridx--;
+ }
+
+ /*
+ * Null terminate the lfn
+ */
+
+ *lfnptr = 0;
+
+ if (badlfn) {
+ longname[0] = 0;
+ return CFE_ERR_FILENOTFOUND;
+ }
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * fat_scandir(fat,chain,name,direntry)
+ *
+ * Scan a single directory looking for a file name
+ *
+ * Input parameters:
+ * fat - FAT filesystem descriptor
+ * chain - FAT chain for directory or NULL for root directory
+ * name - name of file to look for (short or long name)
+ * direntry - place to put directory entry if we find one
+ *
+ * Return value:
+ * 1 if name was found
+ * 0 if name was not found
+ * else <0 is error code
+ ********************************************************************* */
+
+
+static int fat_scandir(fatfs_t *fat,fatchain_t *chain,
+ char *name,uint8_t *direntry)
+{
+ int idx;
+ int count;
+ char shortname[16];
+ char longname[280];
+
+ /*
+ * Get directory size
+ */
+
+ if (chain) {
+ count = (chain->fat_count * fat->fat_bpb.bpb_sectorspercluster) * DIRPERSECTOR;
+ }
+ else {
+ count = (int) fat->fat_bpb.bpb_maxrootdir;
+ }
+
+ /*
+ * Scan whole directory
+ */
+
+ for (idx = 0; idx < count; idx++) {
+
+ /*
+ * Get entry by root or chain depending...
+ */
+
+ if (chain) {
+ fat_getsubdirentry(fat,chain,idx,direntry);
+ }
+ else {
+ fat_getrootdirentry(fat,idx,direntry);
+ }
+
+ /*
+ * Ignore stuff we don't want to see
+ */
+
+ if (direntry[0] == DIRENTRY_LAST) break; /* stop if at end of dir */
+ if (direntry[0] == DIRENTRY_DELETED) continue; /* skip deleted entries */
+ if (direntry[0] == DIRENTRY_PARENTDIR) continue; /* skip ./.. entries */
+
+ if (DIRENTRY_ATTRIB(direntry) == ATTRIB_LFN) continue; /* skip LFNs */
+ if (DIRENTRY_ATTRIB(direntry) & ATTRIB_LABEL) continue; /* skip volume labels */
+
+ /*
+ * Get actual file names from directory
+ */
+
+ fat_getshortname(direntry,shortname);
+ fat_getlongname(fat,chain,idx,direntry,longname);
+
+
+ if (name) {
+ if (strcmpi(name,shortname) == 0) return 1;
+ if (longname[0] && (strcmpi(name,longname) == 0)) return 1;
+ }
+ else {
+ xprintf("%-30s",longname[0] ? longname : shortname);
+// xprintf(" Clus=%04X",DIRENTRY_STARTCLUSTER(direntry));
+// xprintf(" Attrib=%02X",DIRENTRY_ATTRIB(direntry));
+// xprintf(" Size=%d",DIRENTRY_FILELENGTH(direntry));
+ xprintf("%d",DIRENTRY_FILELENGTH(direntry));
+ xprintf("\n");
+ }
+ }
+
+ return 0;
+}
+
+/* *********************************************************************
+ * fat_findfile(fat,name,direntry)
+ *
+ * Locate a directory entry given a complete path name
+ *
+ * Input parameters:
+ * fat - FAT filesystem descriptor
+ * name - name of file to locate (forward or reverse slashses ok)
+ * direntry - place to put directory entry we find
+ *
+ * Return value:
+ * 0 if file not found
+ * 1 if file was found
+ * <0 if error occurs
+ ********************************************************************* */
+
+static int fat_findfile(fatfs_t *fat,char *name,uint8_t *direntry)
+{
+ char *namecopy;
+ char *namepart;
+ char *ptr;
+ fatchain_t chain;
+ int res;
+ int e;
+
+ /*
+ * Copy the name, we're going to hack it up
+ */
+
+ namecopy = strdup(name);
+
+ /*
+ * Chew off the first piece up to the first slash. Remove
+ * a leading slash if it is there.
+ */
+
+ ptr = namecopy;
+
+ if ((*ptr == '/') || (*ptr == '\\')) ptr++;
+
+ namepart = ptr;
+ while (*ptr && (*ptr != '/') && (*ptr != '\\')) ptr++;
+ if (*ptr) *ptr++ = '\0';
+
+ /*
+ * Scan the root directory looking for the first piece
+ */
+
+ res = fat_scandir(fat,NULL,namepart,direntry);
+ if (res == 0) {
+ KFREE(namecopy);
+ return 0; /* file not found */
+ }
+
+
+ /*
+ * Start scanning subdirectories until we run out
+ * of directory components.
+ */
+
+ namepart = ptr;
+ while (*ptr && (*ptr != '/') && (*ptr != '\\')) ptr++;
+ if (*ptr) *ptr++ = '\0';
+ if (!*namepart) namepart = NULL;
+
+
+ while (namepart) {
+
+ /*
+ * Scan the subdirectory
+ */
+
+ e = DIRENTRY_STARTCLUSTER(direntry);
+ memset(&chain,0,sizeof(chain));
+ fat_getchain(fat,e,&chain);
+ res = fat_scandir(fat,&chain,namepart,direntry);
+ if (res == 0) {
+ break;
+ }
+ fat_freechain(&chain);
+
+ /*
+ * Advance to the next piece
+ */
+
+ namepart = ptr;
+ while (*ptr && (*ptr != '/') && (*ptr != '\\')) ptr++;
+ if (*ptr) *ptr++ = '\0';
+ if (!*namepart) namepart = NULL;
+
+ /*
+ * If there's more to go and we hit something that
+ * is not a directory, stop here.
+ */
+
+ if (namepart && !(DIRENTRY_ATTRIB(direntry) & ATTRIB_DIR)) {
+ res = 0;
+ }
+ }
+
+ KFREE(namecopy);
+
+ /*
+ * The last piece we enumerate has to be a file.
+ */
+
+ if ((res > 0) &&
+ (DIRENTRY_ATTRIB(direntry) & ATTRIB_DIR)) {
+ return 0;
+ }
+
+ return res;
+}
+
+
+/* *********************************************************************
+ * fat_init(fat,name)
+ *
+ * Create the filesystem descriptor and attach to the hardware
+ * device.
+ *
+ * Input parameters:
+ * fat - filesystem descriptor
+ * name - hardware device name
+ * part - true to look for partition tables
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int fat_init(fatfs_t *fat,char *name,int part)
+{
+ int res;
+
+ memset(fat,0,sizeof(fatfs_t));
+ fat->fat_dirsecnum = -1;
+ fat->fat_fatsecnum = -1;
+
+ fat->fat_fh = cfe_open(name);
+
+ if (fat->fat_fh < 0) return fat->fat_fh;
+
+ res = fatfs_check_for_partition_table(fat);
+ /* If we were able to figure it out, use that as the default */
+ if (res >= 0) part = res;
+
+ if (part) {
+ res = fat_findpart(fat);
+ if (res < 0) {
+ cfe_close(fat->fat_fh);
+ fat->fat_fh = -1;
+ return res;
+ }
+ }
+
+ res = fat_readbpb(fat);
+ if (res != 0) {
+ cfe_close(fat->fat_fh);
+ fat->fat_fh = -1;
+ return res;
+ }
+
+ return 0;
+}
+
+/* *********************************************************************
+ * fat_uninit(fat)
+ *
+ * Uninit the filesystem descriptor and release any resources
+ * we allocated.
+ *
+ * Input parameters:
+ * fat - filesystem descriptor
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void fat_uninit(fatfs_t *fat)
+{
+ if (fat->fat_fh >= 0) cfe_close(fat->fat_fh);
+ fat->fat_fh = -1;
+}
+
+int fatfs_fileop_dir(void *fsctx);
+int fatfs_fileop_dir(void *fsctx)
+{
+ fatfs_t *fatfs = fsctx;
+ uint8_t direntry[32];
+
+ fat_scandir(fatfs,NULL,NULL,direntry);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * fatfs_fileop_init(fsctx,devname)
+ *
+ * Create a FAT filesystem context and open the associated
+ * block device.
+ *
+ * Input parameters:
+ * fsctx - file system context (return pointer)
+ * devname - device name to open
+ * part - true to look for a partition table
+ *
+ * Return value:
+ * 0 if ok, else error
+ ********************************************************************* */
+
+static int fatfs_fileop_init(void **fsctx,char *devname,int part)
+{
+ int res;
+ fatfs_t *fatfs;
+
+ /*
+ * Allocate a file system context
+ */
+
+ fatfs = (fatfs_t *) KMALLOC(sizeof(fatfs_t),0);
+ if (!fatfs) return CFE_ERR_NOMEM;
+
+ /*
+ * Open a handle to the underlying device
+ */
+
+ res = fat_init(fatfs,devname,part);
+ if (res != 0) {
+ KFREE(fatfs);
+ return res;
+ }
+
+ *fsctx = fatfs;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * fatfs_check_for_partition_table(fatfs)
+ *
+ * This routine attempts to determine if the disk contains a
+ * partition table or if it contains a standard MS-DOS boot recod.
+ * We try to find both, and return what we find, or an error
+ * if it is still unclear.
+ *
+ * Input parameters:
+ * fatfs - fat filesystem context
+ *
+ * Return value:
+ * 0 if no partition table
+ * 1 if partition table
+ * <0 = error occured, could not tell or I/O error
+ ********************************************************************* */
+
+static int fatfs_check_for_partition_table(fatfs_t *fatfs)
+{
+ int res;
+ uint8_t buffer[SECTORSIZE];
+ uint8_t *part;
+ int idx;
+ int foundit = 0;
+
+ /*
+ * Read sector 0
+ */
+
+ fatfs->fat_partstart = 0;
+ res = fat_readsector(fatfs,0,1,buffer);
+ if (res < 0) return res;
+
+ /*
+ * Check the seal at the end of th sector. Both
+ * boot sector and MBR should contain this seal.
+ */
+ if (READWORD(buffer,BPB_SEAL) != BPB_SEAL_VALUE) {
+ res = CFE_ERR_BADFILESYS;
+ return res;
+ }
+
+ /*
+ * See Microsoft Knowledgebase article # Q140418, it contains
+ * a good description of the boot sector format.
+ *
+ * If the extended information is present, and SystemID is "FAT"
+ * and the "bytes per sector" is 512, assume it's a regular boot block
+ */
+
+ if (((buffer[BPB_SIGNATURE] == BPB_SIGNATURE_VALUE1) ||
+ (buffer[BPB_SIGNATURE] == BPB_SIGNATURE_VALUE2)) &&
+ (memcmp(&buffer[BPB_SYSTEMID],"FAT",3) == 0) &&
+ (READWORD(buffer,BPB_BYTESPERSECTOR) == 512)) {
+ /* Not partitioned */
+ res = 0;
+ return res;
+ }
+
+ /* If no extended information is present, check a few other key values. */
+
+ if ((READWORD(buffer,BPB_BYTESPERSECTOR) == 512) &&
+ (READWORD(buffer,BPB_RESERVEDSECTORS) >= 1) &&
+ ((READWORD(buffer,BPB_MEDIADESCRIPTOR) & 0xF0) == 0xF0)) {
+ res = 0;
+ return res;
+ }
+
+ /*
+ * If we're still confused, look for a partition table with a valid FAT
+ * partition on it. We might not detect a partition table that has
+ * only non-FAT partitions on it, like a disk with all Linux partitions,
+ * but that is fine here in the FATFS module, since we only want to
+ * find FAT partitions anyway.
+ */
+ part = &buffer[PTABLE_OFFSET];
+ for (idx = 0; idx < PTABLE_COUNT; idx++) {
+
+ if (((part[PTABLE_STATUS] == PTABLE_STATUS_ACTIVE) ||
+ (part[PTABLE_STATUS] == 0x00)) &&
+ ((part[PTABLE_TYPE] == PARTTYPE_FAT12) ||
+ (part[PTABLE_TYPE] == PARTTYPE_FAT16) ||
+ (part[PTABLE_TYPE] == PARTTYPE_FAT16BIG))) {
+ foundit = 1;
+ res = 1; /*Partition table present*/
+ break;
+ }
+ part += PTABLE_SIZE;
+ }
+
+ /*
+ * If at this point we did not find what we were looking for,
+ * return an error.
+ */
+ if (foundit) {
+ res = 1; /*Partition table is present.*/
+ }
+ else {
+ /*Error! We can't decide if partition table exists or not*/
+ res = CFE_ERR_BADFILESYS;
+ }
+
+ return res;
+}
+
+static int fatfs_fileop_xinit(void **fsctx,void *dev)
+{
+ char *devname = (char *) dev;
+
+ return fatfs_fileop_init(fsctx,devname,0);
+}
+
+static int fatfs_fileop_pinit(void **fsctx,void *dev)
+{
+ char *devname = (char *) dev;
+
+ return fatfs_fileop_init(fsctx,devname,1);
+}
+
+
+
+/* *********************************************************************
+ * fatfs_fileop_open(ref,name)
+ *
+ * Open a file on the FAT device.
+ *
+ * Input parameters:
+ * ref - place to store pointer to fileinfo
+ * fsctx - filesystem context
+ * name - name of file to open
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int fatfs_fileop_open(void **ref,void *fsctx,char *name,int mode)
+{
+ int res;
+ uint8_t direntry[DIRENTRYSIZE];
+ fatfile_t *ff;
+ fatfs_t *fatfs;
+
+ if (mode != FILE_MODE_READ) return CFE_ERR_UNSUPPORTED;
+
+ fatfs = (fatfs_t *) fsctx;
+
+ ff = (fatfile_t *) KMALLOC(sizeof(fatfile_t),0);
+ if (ff == NULL) return CFE_ERR_NOMEM;
+
+ memset(ff,0,sizeof(fatfile_t));
+
+ ff->ff_fat = fatfs;
+
+ res = fat_findfile(ff->ff_fat,name,direntry);
+ if (res <= 0) {
+ return CFE_ERR_FILENOTFOUND; /* not found */
+ }
+
+ /*
+ * Okay, the file was found. Enumerate the FAT chain
+ * associated with this file.
+ */
+
+ ff->ff_filelength = DIRENTRY_FILELENGTH(direntry);
+
+ ff->ff_curpos = 0;
+ ff->ff_cursector = -1;
+
+ res = fat_getchain(ff->ff_fat,
+ DIRENTRY_STARTCLUSTER(direntry),
+ &(ff->ff_chain));
+
+ if (res < 0) {
+ KFREE(ff);
+ return res;
+ }
+
+ /*
+ * Return the file handle
+ */
+
+
+ fatfs->fat_refcnt++;
+ *ref = (void *) ff;
+ return 0;
+}
+
+
+/* *********************************************************************
+ * fatfs_fileop_close(ref)
+ *
+ * Close the file.
+ *
+ * Input parameters:
+ * ref - pointer to open file information
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void fatfs_fileop_close(void *ref)
+{
+ fatfile_t *file = (fatfile_t *) ref;
+ fatfs_t *fatctx = file->ff_fat;
+
+ fatctx->fat_refcnt--;
+
+ fat_freechain(&(file->ff_chain));
+ KFREE(file);
+}
+
+
+/* *********************************************************************
+ * fatfs_fileop_uninit(ref)
+ *
+ * Uninitialize the file system.
+ *
+ * Input parameters:
+ * fsctx - filesystem context
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void fatfs_fileop_uninit(void *fsctx)
+{
+ fatfs_t *fatctx = (fatfs_t *) fsctx;
+
+ if (fatctx->fat_refcnt) {
+ xprintf("fatfs_fileop_unint: warning: refcnt should be zero\n");
+ }
+
+ fat_uninit(fatctx);
+
+ KFREE(fatctx);
+}
+
+
+/* *********************************************************************
+ * fatfs_fileop_seek(ref,offset,how)
+ *
+ * Move the file pointer within the file
+ *
+ * Input parameters:
+ * ref - pointer to open file information
+ * offset - new file location or distance to move
+ * how - method for moving
+ *
+ * Return value:
+ * new file offset
+ * <0 if error occured
+ ********************************************************************* */
+
+static int fatfs_fileop_seek(void *ref,int offset,int how)
+{
+ fatfile_t *file = (fatfile_t *) ref;
+
+ switch (how) {
+ case FILE_SEEK_BEGINNING:
+ file->ff_curpos = offset;
+ break;
+ case FILE_SEEK_CURRENT:
+ file->ff_curpos += offset;
+ break;
+ default:
+ break;
+ }
+
+ if (file->ff_curpos >= file->ff_filelength) {
+ file->ff_curpos = file->ff_filelength;
+ }
+
+ return file->ff_curpos;
+}
+
+
+/* *********************************************************************
+ * fatfs_fileop_read(ref,buf,len)
+ *
+ * Read data from the file.
+ *
+ * Input parameters:
+ * ref - pointer to open file information
+ * buf - buffer to read data into
+ * len - number of bytes to read
+ *
+ * Return value:
+ * number of bytes read
+ * <0 if error occured
+ * 0 means eof
+ ********************************************************************* */
+
+static int fatfs_fileop_read(void *ref,uint8_t *buf,int len)
+{
+ fatfile_t *file = (fatfile_t *) ref;
+ int amtcopy;
+ int ttlcopy = 0;
+ int offset;
+ int sector;
+ int secidx;
+ int origpos;
+ int res;
+ uint8_t temp_buf[SECTORSIZE];
+
+ /*
+ * Remember orig position in case we have an error
+ */
+
+ origpos = file->ff_curpos;
+
+ /*
+ * bounds check the length based on the file length
+ */
+
+ if ((file->ff_curpos + len) > file->ff_filelength) {
+ len = file->ff_filelength - file->ff_curpos;
+ }
+
+ res = 0;
+
+ /*
+ * while ther is still data to be transferred
+ */
+
+
+ while (len) {
+
+ /*
+ * Calculate the sector offset and index in the sector
+ */
+
+ offset = file->ff_curpos % SECTORSIZE;
+ secidx = file->ff_curpos / SECTORSIZE;
+
+ sector = fat_sectoridx(file->ff_fat,&(file->ff_chain),secidx);
+
+ if (sector < 0) {
+ xprintf("should not happen, sector = -1!\n");
+ return sector;
+ }
+
+ /*
+ * first transfer up to the sector boundary
+ */
+
+ amtcopy = len;
+ if (amtcopy > (SECTORSIZE-offset)) {
+ amtcopy = (SECTORSIZE-offset);
+ }
+
+ /*
+ * If transferring exactly a sector, on a sector
+ * boundary, read the data directly into the user buffer
+ *
+ * Extra credit: See if we can transfer more than one
+ * sector at a time, by determining if we can read a run of
+ * contiguous sectors (very likely)
+ *
+ * Otherwise: read into the sector buffer and
+ * transfer the data to user memory.
+ */
+
+ if ((offset == 0) && (amtcopy == SECTORSIZE)) {
+ res = fat_readsector(file->ff_fat,sector,1,temp_buf);
+ if (res < 0) {
+ xprintf("I/O error!\n");
+ break;
+ }
+ memcpy(buf,temp_buf,amtcopy);
+ }
+ else {
+ if (file->ff_cursector != sector) {
+ res = fat_readsector(file->ff_fat,sector,1,file->ff_sector);
+ if (res < 0) {
+ break;
+ }
+ file->ff_cursector = sector;
+ }
+ memcpy(buf,&(file->ff_sector[offset]),amtcopy);
+ }
+
+ /*
+ * Adjust/update all our pointers.
+ */
+
+ buf += amtcopy;
+ file->ff_curpos += amtcopy;
+ ttlcopy += amtcopy;
+ len -= amtcopy;
+
+ /*
+ * see if we ran off the end of the file. Should not
+ * be necessary.
+ */
+
+ if (file->ff_curpos >= file->ff_filelength) {
+ /* should not be necessary */
+ break;
+ }
+ }
+
+ /*
+ * If an error occured, get out now.
+ */
+
+ if (res < 0) {
+ file->ff_curpos = origpos;
+ return res;
+ }
+
+ return ttlcopy;
+
+}
+
+static int fatfs_fileop_write(void *ref,uint8_t *buf,int len)
+{
+ return CFE_ERR_UNSUPPORTED;
+}
+
+
+#if 0
+
+void main(int argc,char *argv[])
+{
+ fatfs_t fat;
+ int idx;
+ unsigned int e;
+ uint8_t direntry[DIRENTRYSIZE];
+ fatchain_t chain;
+ int res;
+
+
+ fat_init(&fat,"floppy.raw");
+
+
+ if (fat_readbpb(&fat) == 0) {
+ fat_dumpbpb(&fat.fat_bpb);
+ }
+
+#if 0
+ for (idx = 0; idx < (int) fat.fat_bpb.bpb_maxrootdir; idx++) {
+ fat_getrootdirentry(&fat,idx,direntry);
+ if (direntry[0] == 0) break;
+ if (direntry[0] == 0xE5) continue;
+ xprintf("%3d: ",idx);
+ fat_dumpdirentry(direntry);
+ }
+#endif
+
+ fat_scandir(&fat,NULL,NULL,direntry);
+
+ for (e = 0x150; e < 0x160; e++) {
+ xprintf("Entry %03X is %03X\n",e,fat_getfatentry(&fat,e));
+ }
+
+#if 0
+ e = 0x36E;
+ while (e != 0xFFF) {
+ e = fat_getfatentry(&fat,e);
+ xprintf("%03X ",e);
+ }
+#endif
+
+
+ xprintf("\n\n");
+ e = 0x36E;
+ memset(&chain,0,sizeof(chain));
+ fat_getchain(&fat,e,&chain);
+ fat_scandir(&fat,&chain,NULL,direntry);
+ fat_freechain(&chain);
+
+ xprintf("\n\n");
+ e = 0x36F;
+ memset(&chain,0,sizeof(chain));
+ fat_getchain(&fat,e,&chain);
+ fat_scandir(&fat,&chain,NULL,direntry);
+ fat_freechain(&chain);
+
+ xprintf("\n\n");
+ e = 0x370;
+ memset(&chain,0,sizeof(chain));
+ fat_getchain(&fat,e,&chain);
+ fat_scandir(&fat,&chain,NULL,direntry);
+ fat_freechain(&chain);
+
+ xprintf("\n\n");
+
+ res = fat_findfile(&fat,argc > 1 ? argv[1] : "/usr/local/include/ansidecl.h",direntry);
+ xprintf("res = %d\n",res);
+
+ if (res) fat_dumpdirentry(direntry);
+
+ close(fat.fat_fh);
+}
+
+void main(int argc,char *argv[])
+{
+ void *ref;
+ int res;
+ char buffer[257];
+ int total = 0;
+
+// res = fatfs_fileop_open(&ref,"floppy.raw:/usr/local/include/bfdlink.h");
+ res = fatfs_fileop_open(&ref,"floppy.raw:/idedrv.h");
+
+ if (res != 0) {
+ xprintf("Could not open file: %d\n",res);
+ exit(1);
+ }
+
+ for (;;) {
+ res = fatfs_fileop_read(ref,buffer,39);
+// xprintf("read returned %d\n",res);
+ if (res <= 0) break;
+
+ if (res > 0) {
+ total += res;
+ buffer[res] = 0;
+ xprintf("%s",buffer);
+ }
+ }
+
+ if (res < 0) xprintf("error! \n");
+
+ xprintf("[total %d]\n",total);
+
+ fatfs_fileop_close(ref);
+
+ exit(0);
+
+}
+
+#endif
diff --git a/cfe/cfe/main/cfe_filesys.c b/cfe/cfe/main/cfe_filesys.c
new file mode 100755
index 0000000..569d7bc
--- /dev/null
+++ b/cfe/cfe/main/cfe_filesys.c
@@ -0,0 +1,343 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Filesystem manager File: cfe_filesys.c
+ *
+ * This module maintains the list of available file systems.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_malloc.h"
+
+#include "cfe_error.h"
+#include "cfe_fileops.h"
+
+#include "cfe.h"
+
+#include "bsp_config.h"
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+extern const fileio_dispatch_t raw_fileops;
+#if CFG_NETWORK
+extern const fileio_dispatch_t tftp_fileops;
+#if (CFG_TCP) && (CFG_HTTPFS)
+extern const fileio_dispatch_t http_fileops;
+#endif
+#endif
+#if CFG_FATFS
+extern const fileio_dispatch_t fatfs_fileops;
+extern const fileio_dispatch_t pfatfs_fileops;
+#endif
+#if CFG_ZLIB
+extern const fileio_dispatch_t zlibfs_fileops;
+#endif
+
+/* *********************************************************************
+ * File system list
+ ********************************************************************* */
+
+static const fileio_dispatch_t * const cfe_filesystems[] = {
+#if !defined(CONFIG_MIPS_BRCM)
+ &raw_fileops,
+#endif
+#if CFG_NETWORK
+ &tftp_fileops,
+#if (CFG_TCP) & (CFG_HTTPFS)
+ &http_fileops,
+#endif
+#endif
+#if CFG_FATFS
+ &fatfs_fileops,
+ &pfatfs_fileops,
+#endif
+#if CFG_ZLIB
+ &zlibfs_fileops,
+#endif
+ NULL
+};
+
+/* *********************************************************************
+ * cfe_findfilesys(name)
+ *
+ * Locate the dispatch record for a particular file system.
+ *
+ * Input parameters:
+ * name - name of filesys to locate
+ *
+ * Return value:
+ * pointer to dispatch table or NULL if not found
+ ********************************************************************* */
+
+const fileio_dispatch_t *cfe_findfilesys(const char *name)
+{
+ const fileio_dispatch_t * const *disp;
+
+ disp = cfe_filesystems;
+
+ while (*disp) {
+ if (strcmp((*disp)->method,name) == 0) return *disp;
+ disp++;
+ }
+
+ return NULL;
+}
+
+/* *********************************************************************
+ * fs_init(name,fsctx,device)
+ *
+ * Initialize a filesystem context
+ *
+ * Input parameters:
+ * name - name of file system
+ * fsctx - returns a filesystem context
+ * device - device name or other info
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+int fs_init(char *fsname,fileio_ctx_t **fsctx,void *device)
+{
+ fileio_ctx_t *ctx;
+ int res;
+ const fileio_dispatch_t *ops;
+
+ ops = cfe_findfilesys((const char *)fsname);
+ if (!ops) return CFE_ERR_FSNOTAVAIL;
+
+ ctx = (fileio_ctx_t *) KMALLOC(sizeof(fileio_ctx_t),0);
+ if (!ctx) return CFE_ERR_NOMEM;
+
+ ctx->ops = ops;
+ res = BDINIT(ops,&(ctx->fsctx),device);
+
+ if (res != 0) {
+ KFREE(ctx);
+ }
+
+ *fsctx = ctx;
+
+ return res;
+}
+
+
+/* *********************************************************************
+ * fs_hook(fsctx,name)
+ *
+ * "Hook" a filesystem to attach a filter, like a decompression
+ * or decryption engine.
+ *
+ * Input parameters:
+ * fsctx - result from a previous fs_init
+ * name - name of fs to hook onto the beginning
+ *
+ * Return value:
+ * 0 if ok
+ * else error
+ ********************************************************************* */
+
+int fs_hook(fileio_ctx_t *fsctx,char *fsname)
+{
+ void *hookfsctx;
+ const fileio_dispatch_t *ops;
+ int res;
+
+ /*
+ * Find the hook filesystem (well, actually a filter)
+ */
+
+ ops = cfe_findfilesys((const char *)fsname);
+ if (!ops) return CFE_ERR_FSNOTAVAIL;
+
+ /*
+ * initialize our hook file filter.
+ */
+
+ res = BDINIT(ops,&hookfsctx,fsctx);
+ if (res != 0) return res;
+
+ /*
+ * Now replace dispatch table for current filesystem
+ * with the hook's dispatch table. When fs_read is called,
+ * we'll go to the hook, and the hook will call the original.
+ *
+ * When fs_uninit is called, the hook will call the original's
+ * uninit routine.
+ */
+
+ fsctx->ops = ops;
+ fsctx->fsctx = hookfsctx;
+
+ return 0;
+
+}
+
+/* *********************************************************************
+ * fs_uninit(fsctx)
+ *
+ * Uninitialize a file system context.
+ *
+ * Input parameters:
+ * fsctx - filesystem context to remove (from fs_init)
+ *
+ * Return value:
+ * 0 if ok
+ * else error
+ ********************************************************************* */
+int fs_uninit(fileio_ctx_t *fsctx)
+{
+ BDUNINIT(fsctx->ops,fsctx->fsctx);
+
+ KFREE(fsctx);
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * fs_open(fsctx,ref,filename,mode)
+ *
+ * Open a file on the file system
+ *
+ * Input parameters:
+ * fsctx - filesystem context (from fs_init)
+ * ref - returns file handle
+ * filename - name of file to open
+ * mode - file open mode
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+int fs_open(fileio_ctx_t *fsctx,void **ref,char *filename,int mode)
+{
+ return BDOPEN2(fsctx->ops,ref,fsctx->fsctx,filename,mode);
+}
+
+/* *********************************************************************
+ * fs_close(fsctx,ref)
+ *
+ * Close a file on the file system
+ *
+ * Input parameters:
+ * fsctx - filesystem context (from fs_init)
+ * ref - file handle (from fs_open)
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+int fs_close(fileio_ctx_t *fsctx,void *ref)
+{
+ BDCLOSE(fsctx->ops,ref);
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * fs_read(fsctx,ref,buffer,len)
+ *
+ * Read data from the device.
+ *
+ * Input parameters:
+ * fsctx - filesystem context (from fs_init)
+ * ref - file handle (from fs_open)
+ * buffer - buffer pointer
+ * len - length
+ *
+ * Return value:
+ * number of bytes read
+ * 0=eof
+ * <0 = error
+ ********************************************************************* */
+
+int fs_read(fileio_ctx_t *fsctx,void *ref,uint8_t *buffer,int len)
+{
+ return BDREAD(fsctx->ops,ref,buffer,len);
+}
+
+/* *********************************************************************
+ * fs_write(fsctx,ref,buffer,len)
+ *
+ * write data from the device.
+ *
+ * Input parameters:
+ * fsctx - filesystem context (from fs_init)
+ * ref - file handle (from fs_open)
+ * buffer - buffer pointer
+ * len - length
+ *
+ * Return value:
+ * number of bytes written
+ * 0=eof
+ * <0 = error
+ ********************************************************************* */
+
+int fs_write(fileio_ctx_t *fsctx,void *ref,uint8_t *buffer,int len)
+{
+ return BDWRITE(fsctx->ops,ref,buffer,len);
+}
+
+/* *********************************************************************
+ * fs_seek(fsctx,ref,offset,how)
+ *
+ * move file pointer on the device
+ *
+ * Input parameters:
+ * fsctx - filesystem context (from fs_init)
+ * ref - file handle (from fs_open)
+ * offset - distance to move
+ * how - origin (FILE_SEEK_xxx)
+ *
+ * Return value:
+ * new offset
+ * <0 = error
+ ********************************************************************* */
+
+int fs_seek(fileio_ctx_t *fsctx,void *ref,int offset,int how)
+{
+ return BDSEEK(fsctx->ops,ref,offset,how);
+}
diff --git a/cfe/cfe/main/cfe_httpfs.c b/cfe/cfe/main/cfe_httpfs.c
new file mode 100644
index 0000000..4ebad4c
--- /dev/null
+++ b/cfe/cfe/main/cfe_httpfs.c
@@ -0,0 +1,396 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * "HTTP" file system File: cfe_httpfs.c
+ *
+ * This filesystem driver lets you read files from an HTTP
+ * server.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_error.h"
+#include "cfe_fileops.h"
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_console.h"
+
+#include "cfe.h"
+
+#include "bsp_config.h"
+
+#if (CFG_TCP) && (CFG_HTTPFS)
+
+#include "net_ebuf.h"
+#include "net_api.h"
+
+
+/* *********************************************************************
+ * HTTP context
+ ********************************************************************* */
+
+/*
+ * File system context - describes overall file system info,
+ * such as the handle to the underlying device.
+ */
+
+typedef struct http_fsctx_s {
+ int http_tmp; /* context not really needed */
+} http_fsctx_t;
+
+/*
+ * File context - describes an open file on the file system.
+ */
+
+#define HTTP_BUFSIZE 1024
+typedef struct http_file_s {
+ http_fsctx_t *http_fsctx;
+ int http_socket;
+ uint8_t http_buffer[HTTP_BUFSIZE];
+ uint8_t *http_bptr;
+ int http_blen;
+ int http_offset;
+ char *http_filename;
+} http_file_t;
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+static int http_fileop_init(void **fsctx,void *devicename);
+static int http_fileop_open(void **ref,void *fsctx,char *filename,int mode);
+static int http_fileop_read(void *ref,uint8_t *buf,int len);
+static int http_fileop_write(void *ref,uint8_t *buf,int len);
+static int http_fileop_seek(void *ref,int offset,int how);
+static void http_fileop_close(void *ref);
+static void http_fileop_uninit(void *fsctx);
+
+/* *********************************************************************
+ * RAW fileio dispatch table
+ ********************************************************************* */
+
+const fileio_dispatch_t http_fileops = {
+ "http",
+ FSYS_TYPE_NETWORK,
+ http_fileop_init,
+ http_fileop_open,
+ http_fileop_read,
+ http_fileop_write,
+ http_fileop_seek,
+ http_fileop_close,
+ http_fileop_uninit
+};
+
+static int http_fileop_init(void **newfsctx,void *dev)
+{
+ http_fsctx_t *fsctx;
+
+ *newfsctx = NULL;
+
+ fsctx = KMALLOC(sizeof(http_fsctx_t),0);
+ if (!fsctx) {
+ return CFE_ERR_NOMEM;
+ }
+
+ fsctx->http_tmp = 0;
+ *newfsctx = fsctx;
+
+ return 0;
+}
+
+static int http_fileop_open(void **ref,void *fsctx_arg,char *filename,int mode)
+{
+ http_fsctx_t *fsctx;
+ http_file_t *file;
+ char temp[200];
+ char *hostname, *filen;
+ int hlen;
+ int termidx;
+ int res;
+ int err = 0;
+ char *hptr;
+ char *tok;
+ uint8_t hostaddr[IP_ADDR_LEN];
+ uint8_t termstr[4];
+ uint8_t b;
+
+ if (mode != FILE_MODE_READ) return CFE_ERR_UNSUPPORTED;
+
+ fsctx = (http_fsctx_t *) fsctx_arg;
+
+ file = KMALLOC(sizeof(http_file_t),0);
+ if (!file) {
+ return CFE_ERR_NOMEM;
+ }
+
+ file->http_filename = lib_strdup(filename);
+ if (!file->http_filename) {
+ KFREE(file);
+ return CFE_ERR_NOMEM;
+ }
+
+ lib_chop_filename(file->http_filename,&hostname,&filen);
+
+ /*
+ * Look up remote host
+ */
+
+ res = dns_lookup(hostname,hostaddr);
+ if (res < 0) {
+ KFREE(file);
+ return res;
+ }
+
+ file->http_socket = tcp_socket();
+ if (file->http_socket < 0) {
+ KFREE(file->http_filename);
+ KFREE(file);
+ return -1;
+ }
+
+ /*
+ * Connect to remote host.
+ */
+
+ tcp_setflags(file->http_socket,0); /* set socket to blocking */
+ res = tcp_connect(file->http_socket,hostaddr,80);
+
+ if (res < 0) {
+ tcp_close(file->http_socket);
+ KFREE(file->http_filename);
+ KFREE(file);
+ return res;
+ }
+
+ /*
+ * Send GET command. Supply the hostname (for HTTP 1.1 requirements)
+ * and set the connection to close as soon as all the data is received.
+ */
+
+ hlen = sprintf(temp,"GET /%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n",filen,hostname);
+
+ res = tcp_send(file->http_socket,temp,hlen);
+ if (res < 0) {
+ tcp_close(file->http_socket);
+ KFREE(file->http_filename);
+ KFREE(file);
+ return res;
+ }
+
+ /*
+ * Read bytes until we either reach EOF or we see "\r\n\r\n"
+ * This is the server's status string.
+ */
+
+ termstr[0] = '\r'; termstr[1] = '\n';
+ termstr[2] = '\r'; termstr[3] = '\n';
+ termidx = 0;
+
+ file->http_offset = 0;
+ file->http_blen = 0;
+ file->http_bptr = file->http_buffer;
+
+ res = 0;
+ for (;;) {
+ res = tcp_recv(file->http_socket,&b,1);
+ if (res < 0) break;
+ if (b == termstr[termidx]) {
+ termidx++;
+ if (termidx == 4) break;
+ }
+ else {
+ termidx = 0;
+ }
+
+ /*
+ * Save the bytes from the header up to our buffer
+ * size. It's okay if we don't save it all,
+ * since all we want is the result code which comes
+ * first.
+ */
+
+ if (file->http_blen < (HTTP_BUFSIZE-1)) {
+ *(file->http_bptr) = b;
+ file->http_bptr++;
+ file->http_blen++;
+ }
+ }
+
+ /*
+ * Premature EOFs are not good, bail now.
+ */
+
+ if (res < 0) {
+ err = CFE_ERR_EOF;
+ goto protocolerr;
+ }
+
+ /*
+ * Skip past the HTTP response header and grab the result code.
+ * Sanity check it a little.
+ */
+
+ *(file->http_bptr) = 0;
+
+ hptr = file->http_buffer;
+ tok = lib_gettoken(&hptr);
+ if (!tok || (memcmp(tok,"HTTP",4) != 0)) {
+ err = CFE_ERR_PROTOCOLERR;
+ goto protocolerr;
+ }
+
+ tok = lib_gettoken(&hptr);
+ if (!tok) {
+ err = CFE_ERR_PROTOCOLERR;
+ goto protocolerr;
+ }
+
+ switch (lib_atoi(tok)) {
+ case 200:
+ err = 0;
+ break;
+ case 404:
+ err = CFE_ERR_FILENOTFOUND;
+ break;
+
+ }
+
+ /*
+ * If we get to here, the file is okay and we're about to receive data.
+ */
+
+ if (err == 0) {
+ *ref = file;
+ return 0;
+ }
+
+protocolerr:
+ tcp_close(file->http_socket);
+ KFREE(file->http_filename);
+ KFREE(file);
+ *ref = NULL;
+ return err;
+}
+
+static int http_fileop_read(void *ref,uint8_t *buf,int len)
+{
+ http_file_t *file = (http_file_t *) ref;
+ int res;
+
+ res = tcp_recv(file->http_socket,buf,len);
+
+ if (res > 0) {
+ file->http_offset += res;
+ return res;
+ }
+
+ return 0; /* Any error becomes "EOF" */
+}
+
+static int http_fileop_write(void *ref,uint8_t *buf,int len)
+{
+ return CFE_ERR_UNSUPPORTED;
+}
+
+static int http_fileop_seek(void *ref,int offset,int how)
+{
+ http_file_t *file = (http_file_t *) ref;
+ int newoffset;
+ int res;
+ int buflen;
+
+ switch (how) {
+ case FILE_SEEK_BEGINNING:
+ newoffset = offset;
+ break;
+ case FILE_SEEK_CURRENT:
+ newoffset = file->http_offset + offset;
+ break;
+ default:
+ newoffset = offset;
+ break;
+ }
+
+ /*
+ * Can't seek backwards.
+ */
+ if (newoffset < file->http_offset) {
+ return CFE_ERR_UNSUPPORTED;
+ }
+
+ /*
+ * Eat data till offset reaches where we want.
+ */
+
+ while (file->http_offset != newoffset) {
+ buflen = HTTP_BUFSIZE;
+ if (buflen > (newoffset - file->http_offset)) buflen = (newoffset-file->http_offset);
+ res = tcp_recv(file->http_socket,file->http_buffer,buflen);
+ if (res < 0) break;
+ file->http_offset += res;
+ }
+
+ return file->http_offset;
+}
+
+
+static void http_fileop_close(void *ref)
+{
+ http_file_t *file = (http_file_t *) ref;
+
+ tcp_close(file->http_socket);
+ KFREE(file->http_filename);
+ KFREE(file);
+}
+
+static void http_fileop_uninit(void *fsctx_arg)
+{
+ http_fsctx_t *fsctx = (http_fsctx_t *) fsctx_arg;
+
+ KFREE(fsctx);
+}
+
+#endif
diff --git a/cfe/cfe/main/cfe_iocb_dispatch.c b/cfe/cfe/main/cfe_iocb_dispatch.c
new file mode 100755
index 0000000..24aea0a
--- /dev/null
+++ b/cfe/cfe/main/cfe_iocb_dispatch.c
@@ -0,0 +1,647 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * IOCB dispatcher File: cfe_iocb_dispatch.c
+ *
+ * This routine is the main API dispatch for CFE. User API
+ * calls, via the ROM entry point, get dispatched to routines
+ * in this module.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "cfe_iocb.h"
+#include "cfe_error.h"
+#include "cfe_device.h"
+#include "cfe_timer.h"
+#include "cfe_mem.h"
+#include "cfe_fileops.h"
+#include "cfe_boot.h"
+#include "env_subr.h"
+#include "cfe.h"
+#include "cfe_console.h"
+#include "bsp_config.h"
+#include "initdata.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define HV 1 /* handle valid */
+
+#ifndef CFG_BOARD_ID
+#define CFG_BOARD_ID 0
+#endif
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+cfe_devctx_t *cfe_handle_table[CFE_MAX_HANDLE];
+
+extern void _cfe_flushcache(int);
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+int cfe_iocb_dispatch(cfe_iocb_t *iocb);
+void cfe_device_poll(void *);
+
+#if CFG_MULTI_CPUS
+extern int altcpu_cmd_start(uint64_t,uint64_t *);
+extern int altcpu_cmd_stop(uint64_t);
+#endif
+
+/* *********************************************************************
+ * Dispatch table
+ ********************************************************************* */
+
+struct cfe_cmd_dispatch_s {
+ int plistsize;
+ int flags;
+ int (*func)(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+};
+
+
+static int cfe_cmd_fw_getinfo(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_fw_restart(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_fw_boot(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_fw_cpuctl(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_fw_gettime(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_fw_memenum(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_fw_flushcache(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+
+static int cfe_cmd_dev_gethandle(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_dev_enum(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_dev_open(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_dev_inpstat(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_dev_read(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_dev_write(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_dev_ioctl(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_dev_close(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_dev_getinfo(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+
+static int cfe_cmd_env_enum(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_env_get(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_env_set(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+static int cfe_cmd_env_del(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+
+const static struct cfe_cmd_dispatch_s cfe_cmd_dispatch_table[CFE_CMD_MAX] = {
+ {sizeof(iocb_fwinfo_t), 0, cfe_cmd_fw_getinfo}, /* 0 : CFE_CMD_FW_GETINFO */
+ {sizeof(iocb_exitstat_t),0, cfe_cmd_fw_restart}, /* 1 : CFE_CMD_FW_RESTART */
+ {sizeof(iocb_buffer_t), 0, cfe_cmd_fw_boot}, /* 2 : CFE_CMD_FW_BOOT */
+ {sizeof(iocb_cpuctl_t), 0, cfe_cmd_fw_cpuctl}, /* 3 : CFE_CMD_FW_CPUCTL */
+ {sizeof(iocb_time_t), 0, cfe_cmd_fw_gettime}, /* 4 : CFE_CMD_FW_GETTIME */
+ {sizeof(iocb_meminfo_t),0, cfe_cmd_fw_memenum}, /* 5 : CFE_CMD_FW_MEMENUM */
+ {0, 0, cfe_cmd_fw_flushcache}, /* 6 : CFE_CMD_FW_FLUSHCACHE */
+ {-1, 0, NULL}, /* 7 : */
+ {-1, 0, NULL}, /* 8 : */
+ {0, 0, cfe_cmd_dev_gethandle}, /* 9 : CFE_CMD_DEV_GETHANDLE */
+ {sizeof(iocb_envbuf_t), 0, cfe_cmd_dev_enum}, /* 10 : CFE_CMD_DEV_ENUM */
+ {sizeof(iocb_buffer_t), 0, cfe_cmd_dev_open}, /* 11 : CFE_CMD_DEV_OPEN */
+ {sizeof(iocb_inpstat_t),HV, cfe_cmd_dev_inpstat}, /* 12 : CFE_CMD_DEV_INPSTAT */
+ {sizeof(iocb_buffer_t), HV, cfe_cmd_dev_read}, /* 13 : CFE_CMD_DEV_READ */
+ {sizeof(iocb_buffer_t), HV, cfe_cmd_dev_write}, /* 14 : CFE_CMD_DEV_WRITE */
+ {sizeof(iocb_buffer_t), HV, cfe_cmd_dev_ioctl}, /* 15 : CFE_CMD_DEV_IOCTL */
+ {0, HV, cfe_cmd_dev_close}, /* 16 : CFE_CMD_DEV_CLOSE */
+ {sizeof(iocb_buffer_t), 0, cfe_cmd_dev_getinfo}, /* 17 : CFE_CMD_DEV_GETINFO */
+ {-1, 0, NULL}, /* 18 : */
+ {-1, 0, NULL}, /* 19 : */
+ {sizeof(iocb_envbuf_t), 0, cfe_cmd_env_enum}, /* 20 : CFE_CMD_ENV_ENUM */
+ {-1, 0, NULL}, /* 21 : */
+ {sizeof(iocb_envbuf_t), 0, cfe_cmd_env_get}, /* 22 : CFE_CMD_ENV_GET */
+ {sizeof(iocb_envbuf_t), 0, cfe_cmd_env_set}, /* 23 : CFE_CMD_ENV_SET */
+ {sizeof(iocb_envbuf_t), 0, cfe_cmd_env_del}, /* 24 : CFE_CMD_ENV_DEL */
+ {-1, 0, NULL}, /* 25 : */
+ {-1, 0, NULL}, /* 26 : */
+ {-1, 0, NULL}, /* 27 : */
+ {-1, 0, NULL}, /* 28 : */
+ {-1, 0, NULL}, /* 29 : */
+ {-1, 0, NULL}, /* 30 : */
+ {-1, 0, NULL} /* 31 : */
+};
+
+/* *********************************************************************
+ * IOCB dispatch routines
+ ********************************************************************* */
+
+void cfe_device_poll(void *x)
+{
+ int idx;
+ cfe_devctx_t **ctx = cfe_handle_table;
+
+ for (idx = 0; idx < CFE_MAX_HANDLE; idx++,ctx++) {
+ if ((*ctx) && ((*ctx)->dev_dev->dev_dispatch->dev_poll)) {
+ (*ctx)->dev_dev->dev_dispatch->dev_poll(*ctx,cfe_ticks);
+ }
+ }
+}
+
+int cfe_iocb_dispatch(cfe_iocb_t *iocb)
+{
+ const struct cfe_cmd_dispatch_s *disp;
+ int res;
+ cfe_devctx_t *ctx;
+
+ /*
+ * Check for commands codes out of range
+ */
+
+ if ((iocb->iocb_fcode < 0) || (iocb->iocb_fcode >= CFE_CMD_MAX)) {
+ iocb->iocb_status = CFE_ERR_INV_COMMAND;
+ return iocb->iocb_status;
+ }
+
+ /*
+ * Check for command codes in range but invalid
+ */
+
+ disp = &cfe_cmd_dispatch_table[iocb->iocb_fcode];
+
+ if (disp->plistsize < 0) {
+ iocb->iocb_status = CFE_ERR_INV_COMMAND;
+ return iocb->iocb_status;
+ }
+
+ /*
+ * Check for invalid parameter list size
+ */
+
+ if (disp->plistsize != iocb->iocb_psize) {
+ iocb->iocb_status = CFE_ERR_INV_PARAM;
+ return iocb->iocb_status;
+ }
+
+ /*
+ * Determine handle
+ */
+
+ ctx = NULL;
+ if (disp->flags & HV) {
+ if ((iocb->iocb_handle >= CFE_MAX_HANDLE) ||
+ (iocb->iocb_handle < 0) ||
+ (cfe_handle_table[iocb->iocb_handle] == NULL)){
+ iocb->iocb_status = CFE_ERR_INV_PARAM;
+ return iocb->iocb_status;
+ }
+ ctx = cfe_handle_table[iocb->iocb_handle];
+ }
+
+ /*
+ * Dispatch to handler routine
+ */
+
+ res = (*disp->func)(ctx,iocb);
+
+ iocb->iocb_status = res;
+ return res;
+}
+
+static int cfe_newhandle(void)
+{
+ int idx;
+
+ for (idx = 0; idx < CFE_MAX_HANDLE; idx++) {
+ if (cfe_handle_table[idx] == NULL) break;
+ }
+
+ if (idx == CFE_MAX_HANDLE) return -1;
+
+ return idx;
+}
+
+
+/* *********************************************************************
+ * Implementation routines for each IOCB function
+ ********************************************************************* */
+
+static int cfe_cmd_fw_getinfo(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ iocb_fwinfo_t *info = &iocb->plist.iocb_fwinfo;
+
+ info->fwi_version = (CFE_VER_MAJOR << 16) |
+ (CFE_VER_MINOR << 8) |
+ (CFE_VER_BUILD);
+ info->fwi_totalmem = ((cfe_int64_t) mem_totalsize) << 20;
+ info->fwi_flags =
+#ifdef __long64
+ CFE_FWI_64BIT |
+#else
+ CFE_FWI_32BIT |
+#endif
+#if (CFG_EMBEDDED_PIC)
+ CFE_FWI_RELOC |
+#endif
+#if (!CFG_RUNFROMKSEG0)
+ CFE_FWI_UNCACHED |
+#endif
+#if CFG_MULTI_CPUS
+ CFE_FWI_MULTICPU |
+#endif
+#ifdef _VERILOG_
+ CFE_FWI_RTLSIM |
+#endif
+#ifdef _FUNCSIM_
+ CFE_FWI_FUNCSIM |
+#endif
+ 0;
+
+ info->fwi_boardid = CFG_BOARD_ID;
+ info->fwi_bootarea_pa = (cfe_int64_t) mem_bootarea_start;
+ info->fwi_bootarea_va = BOOT_START_ADDRESS;
+ info->fwi_bootarea_size = (cfe_int64_t) mem_bootarea_size;
+ info->fwi_reserved1 = 0;
+ info->fwi_reserved2 = 0;
+ info->fwi_reserved3 = 0;
+
+ return CFE_OK;
+}
+
+static int cfe_cmd_fw_restart(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ if (iocb->iocb_flags & CFE_FLG_WARMSTART) {
+ cfe_warmstart(iocb->plist.iocb_exitstat.status);
+ }
+ else {
+ cfe_restart();
+ }
+
+ /* should not get here */
+
+ return CFE_OK;
+}
+
+static int cfe_cmd_fw_boot(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ return CFE_ERR_INV_COMMAND; /* not implemented yet */
+}
+
+static int cfe_cmd_fw_cpuctl(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+#if CFG_MULTI_CPUS
+ int res;
+ uint64_t startargs[4];
+
+ switch (iocb->plist.iocb_cpuctl.cpu_command) {
+ case CFE_CPU_CMD_START:
+
+ startargs[0] = iocb->plist.iocb_cpuctl.start_addr;
+ startargs[1] = iocb->plist.iocb_cpuctl.sp_val;
+ startargs[2] = iocb->plist.iocb_cpuctl.gp_val;
+ startargs[3] = iocb->plist.iocb_cpuctl.a1_val;
+
+ res = altcpu_cmd_start(iocb->plist.iocb_cpuctl.cpu_number,
+ startargs);
+ break;
+ case CFE_CPU_CMD_STOP:
+ res = altcpu_cmd_stop(iocb->plist.iocb_cpuctl.cpu_number);
+ break;
+ default:
+ res = CFE_ERR_INV_PARAM;
+ }
+
+ return res;
+#else
+ return CFE_ERR_INV_COMMAND;
+#endif
+}
+
+static int cfe_cmd_fw_gettime(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ POLL();
+
+ iocb->plist.iocb_time.ticks = cfe_ticks;
+
+ return CFE_OK;
+}
+
+static int cfe_cmd_fw_memenum(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int type;
+ int res;
+ uint64_t addr,size;
+
+ res = cfe_arena_enum(iocb->plist.iocb_meminfo.mi_idx,
+ &type,
+ &addr,
+ &size,
+ (iocb->iocb_flags & CFE_FLG_FULL_ARENA) ? TRUE : FALSE);
+
+ iocb->plist.iocb_meminfo.mi_addr = addr;
+ iocb->plist.iocb_meminfo.mi_size = size;
+ iocb->plist.iocb_meminfo.mi_type = type;
+
+ if (res == 0) {
+ if (type == MEMTYPE_DRAM_AVAILABLE) {
+ iocb->plist.iocb_meminfo.mi_type = CFE_MI_AVAILABLE;
+ }
+ else {
+ iocb->plist.iocb_meminfo.mi_type = CFE_MI_RESERVED;
+ }
+ }
+
+ return res;
+}
+
+static int cfe_cmd_fw_flushcache(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ _cfe_flushcache(iocb->iocb_flags);
+ return CFE_OK;
+}
+
+static int cfe_cmd_dev_enum(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ return CFE_ERR_INV_COMMAND;
+}
+
+static int cfe_cmd_dev_gethandle(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ switch (iocb->iocb_flags) {
+ case CFE_STDHANDLE_CONSOLE:
+ if (console_handle == -1) return CFE_ERR_DEVNOTFOUND;
+ iocb->iocb_handle = console_handle;
+ return CFE_OK;
+ break;
+ default:
+ return CFE_ERR_INV_PARAM;
+ }
+}
+
+static int cfe_cmd_dev_open(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int h;
+ cfe_device_t *dev;
+ char devname[64];
+ int res;
+
+ /*
+ * Get device name
+ */
+
+ xstrncpy(devname,(char*)iocb->plist.iocb_buffer.buf_ptr,sizeof(devname));
+
+ /*
+ * Find device in device table
+ */
+
+ dev = cfe_finddev(devname);
+ if (!dev) return CFE_ERR_DEVNOTFOUND;
+
+ /*
+ * Fail if someone else already has the device open
+ */
+
+ if (dev->dev_opencount > 0) return CFE_ERR_DEVOPEN;
+
+ /*
+ * Generate a new handle
+ */
+
+ h = cfe_newhandle();
+ if (h < 0) return CFE_ERR_NOMEM;
+
+ /*
+ * Allocate a context
+ */
+
+ ctx = (cfe_devctx_t *) KMALLOC(sizeof(cfe_devctx_t),0);
+ if (ctx == NULL) return CFE_ERR_NOMEM;
+
+ /*
+ * Fill in the context
+ */
+
+ ctx->dev_dev = dev;
+ ctx->dev_softc = dev->dev_softc;
+ ctx->dev_openinfo = NULL;
+
+ /*
+ * Call driver's open func
+ */
+
+ res = dev->dev_dispatch->dev_open(ctx);
+
+ if (res != 0) {
+ KFREE(ctx);
+ return res;
+ }
+
+ /*
+ * Increment refcnt and save handle
+ */
+
+ dev->dev_opencount++;
+ cfe_handle_table[h] = ctx;
+ iocb->iocb_handle = h;
+
+ /*
+ * Success!
+ */
+
+ return CFE_OK;
+}
+
+static int cfe_cmd_dev_inpstat(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int status;
+
+ status = ctx->dev_dev->dev_dispatch->dev_inpstat(ctx,&(iocb->plist.iocb_inpstat));
+
+ return status;
+}
+
+static int cfe_cmd_dev_read(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int status;
+
+ status = ctx->dev_dev->dev_dispatch->dev_read(ctx,&(iocb->plist.iocb_buffer));
+
+ return status;
+}
+
+static int cfe_cmd_dev_write(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int status;
+
+ status = ctx->dev_dev->dev_dispatch->dev_write(ctx,&(iocb->plist.iocb_buffer));
+
+ return status;
+}
+
+static int cfe_cmd_dev_ioctl(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int status;
+
+ status = ctx->dev_dev->dev_dispatch->dev_ioctl(ctx,&(iocb->plist.iocb_buffer));
+
+ return status;
+}
+
+static int cfe_cmd_dev_close(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ /*
+ * Call device close function
+ */
+
+ ctx->dev_dev->dev_dispatch->dev_close(ctx);
+
+ /*
+ * Decrement refcnt
+ */
+
+ ctx->dev_dev->dev_opencount--;
+
+ /*
+ * Wipe out handle
+ */
+
+ cfe_handle_table[iocb->iocb_handle] = NULL;
+
+ /*
+ * Release device context
+ */
+
+ KFREE(ctx);
+
+ return CFE_OK;
+}
+
+static int cfe_cmd_dev_getinfo(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ cfe_device_t *dev;
+ char devname[64];
+ char *x;
+
+ /*
+ * Get device name
+ */
+
+ xstrncpy(devname,(char*)iocb->plist.iocb_buffer.buf_ptr,sizeof(devname));
+
+ /*
+ * Find device in device table
+ */
+
+ if ((x = strchr(devname,':'))) *x = '\0';
+ dev = cfe_finddev(devname);
+ if (!dev) return CFE_ERR_DEVNOTFOUND;
+
+ /*
+ * Return device class
+ */
+
+ iocb->plist.iocb_buffer.buf_devflags = dev->dev_class;
+
+ return CFE_OK;
+}
+
+static int cfe_cmd_env_enum(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int vallen,namelen,res;
+
+ namelen = iocb->plist.iocb_envbuf.name_length;
+ vallen = iocb->plist.iocb_envbuf.val_length;
+
+ res = env_enum(iocb->plist.iocb_envbuf.enum_idx,
+ (char*)iocb->plist.iocb_envbuf.name_ptr,
+ &namelen,
+ (char*)iocb->plist.iocb_envbuf.val_ptr,
+ &vallen);
+
+ if (res < 0) return CFE_ERR_ENVNOTFOUND;
+
+ return CFE_OK;
+}
+
+
+static int cfe_cmd_env_get(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ char *env;
+
+ env = env_getenv((char*)iocb->plist.iocb_envbuf.name_ptr);
+
+ if (env == NULL) return CFE_ERR_ENVNOTFOUND;
+
+ xstrncpy((char*)iocb->plist.iocb_envbuf.val_ptr,
+ env,
+ iocb->plist.iocb_envbuf.val_length);
+
+ return CFE_OK;
+}
+
+static int cfe_cmd_env_set(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int res;
+ int flg;
+
+
+ flg = (iocb->iocb_flags & CFE_FLG_ENV_PERMANENT) ?
+ ENV_FLG_NORMAL : ENV_FLG_BUILTIN;
+
+ res = env_setenv((char*)iocb->plist.iocb_envbuf.name_ptr,
+ (char*)iocb->plist.iocb_envbuf.val_ptr,
+ flg);
+
+ if (res == 0) {
+ if (iocb->iocb_flags & CFE_FLG_ENV_PERMANENT) res = env_save();
+ }
+
+ if (res < 0) return res;
+
+ return CFE_OK;
+}
+
+static int cfe_cmd_env_del(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ int res;
+
+ res = env_delenv((char*)iocb->plist.iocb_envbuf.name_ptr);
+
+ return res;
+}
+
+
+
diff --git a/cfe/cfe/main/cfe_ldr_elf.c b/cfe/cfe/main/cfe_ldr_elf.c
new file mode 100644
index 0000000..0581241
--- /dev/null
+++ b/cfe/cfe/main/cfe_ldr_elf.c
@@ -0,0 +1,396 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * ELF Program Loader File: cfe_ldr_elf.c
+ *
+ * This program parses ELF executables and loads them into memory.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_error.h"
+#include "cfe_devfuncs.h"
+#include "cfe_timer.h"
+#include "cfe_mem.h"
+
+#include "cfe.h"
+#include "cfe_loader.h"
+#include "cfe_fileops.h"
+#include "elf.h"
+
+#include "cfe_boot.h"
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+static int cfe_elfload(cfe_loadargs_t *la);
+
+const cfe_loader_t elfloader = {
+ "elf",
+ cfe_elfload,
+ 0};
+
+/* *********************************************************************
+ * readprogsegment(fsctx,ref,addr,size)
+ *
+ * Read a program segment, generally corresponding to one
+ * section of the file.
+ *
+ * Input parameters:
+ * fsctx - file I/O dispatch
+ * ref - reference data for open file handle
+ * addr - target virtual address
+ * size - size of region to read
+ *
+ * Return value:
+ * Number of bytes copied or <0 if error occured
+ ********************************************************************* */
+
+static int readprogsegment(fileio_ctx_t *fsctx,void *ref,
+ void *addr,int size,int flags)
+{
+ int res;
+
+#ifdef __long64
+ if (flags & LOADFLG_NOISY) xprintf("0x%016llx/%d ",addr,size);
+#else
+ if (flags & LOADFLG_NOISY) xprintf("0x%x/%d ",addr,size);
+#endif
+
+ if (!cfe_arena_loadcheck((uintptr_t) addr,size)) {
+ return CFE_ERR_BADADDR;
+ }
+
+ res = fs_read(fsctx,ref,addr,size);
+
+ if (res < 0) return CFE_ERR_IOERR;
+ if (res != size) return CFE_ERR_BADELFFMT;
+
+ return size;
+}
+
+
+/* *********************************************************************
+ * readclearbss(addr,size)
+ *
+ * Process a BSS section, zeroing memory corresponding to
+ * the BSS.
+ *
+ * Input parameters:
+ * addr - address to zero
+ * size - length of area to zero
+ *
+ * Return value:
+ * number of zeroed bytes or <0 if error occured
+ ********************************************************************* */
+
+static int readclearbss(void *addr,int size,int flags)
+{
+
+#ifdef __long64
+ if (flags & LOADFLG_NOISY) xprintf("0x%016llx/%d ",addr,size);
+#else
+ if (flags & LOADFLG_NOISY) xprintf("0x%x/%d ",addr,size);
+#endif
+
+ if (!cfe_arena_loadcheck((uintptr_t) addr,size)) {
+ return CFE_ERR_BADADDR;
+ }
+
+ if (size > 0) memset(addr,0,size);
+ return size;
+}
+
+
+/* *********************************************************************
+ * elfgetshdr(ops,ref,ep)
+ *
+ * Get a section header from the ELF file
+ *
+ * Input parameters:
+ * ops - file I/O dispatch
+ * ref - reference data for open file
+ * ep - extended header info
+ *
+ * Return value:
+ * copy of section header (malloc'd) or NULL if no memory
+ ********************************************************************* */
+
+static Elf32_Shdr *elfgetshdr(fileio_ctx_t *fsctx,void *ref,Elf32_Ehdr *ep)
+{
+ Elf32_Shdr *shtab;
+ unsigned size = ep->e_shnum * sizeof(Elf32_Shdr);
+
+ shtab = (Elf32_Shdr *) KMALLOC(size,0);
+ if (!shtab) {
+ return NULL;
+ }
+
+ if (fs_seek(fsctx,ref,ep->e_shoff,FILE_SEEK_BEGINNING) != ep->e_shoff ||
+ fs_read(fsctx,ref,(uint8_t *)shtab,size) != size) {
+ KFREE(shtab);
+ return NULL;
+ }
+
+ return (shtab);
+}
+
+/* *********************************************************************
+ * elfload_internal(ops,ref,entrypt,flags)
+ *
+ * Read an ELF file (main routine)
+ *
+ * Input parameters:
+ * ops - file I/O dispatch
+ * ref - open file handle
+ * entrypt - filled in with entry vector
+ * flags - generic boot flags
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int elfload_internal(fileio_ctx_t *fsctx,void *ref,
+ unsigned long *entrypt,int flags)
+{
+ Elf32_Ehdr *ep;
+ Elf32_Phdr *phtab = 0;
+ Elf32_Shdr *shtab = 0;
+ unsigned int nbytes;
+ int i;
+ int res;
+ Elf32_Ehdr ehdr;
+
+ ep = &ehdr;
+ if (fs_read(fsctx,ref,(uint8_t *) ep,sizeof(*ep)) != sizeof(*ep)) {
+ return CFE_ERR_IOERR;
+ }
+
+ /* check header validity */
+ if (ep->e_ident[EI_MAG0] != ELFMAG0 ||
+ ep->e_ident[EI_MAG1] != ELFMAG1 ||
+ ep->e_ident[EI_MAG2] != ELFMAG2 ||
+ ep->e_ident[EI_MAG3] != ELFMAG3) {
+ return CFE_ERR_NOTELF;
+ }
+
+ if (ep->e_ident[EI_CLASS] != ELFCLASS32) return CFE_ERR_NOT32BIT;
+
+#ifdef __MIPSEB
+ if (ep->e_ident[EI_DATA] != ELFDATA2MSB) return CFE_ERR_WRONGENDIAN; /* big endian */
+#endif
+#ifdef __MIPSEL
+ if (ep->e_ident[EI_DATA] != ELFDATA2LSB) return CFE_ERR_WRONGENDIAN; /* little endian */
+#endif
+
+ if (ep->e_ident[EI_VERSION] != EV_CURRENT) return CFE_ERR_BADELFVERS;
+ if (ep->e_machine != EM_MIPS) return CFE_ERR_NOTMIPS;
+
+ /* Is there a program header? */
+ if (ep->e_phoff == 0 || ep->e_phnum == 0 ||
+ ep->e_phentsize != sizeof(Elf32_Phdr)) {
+ return CFE_ERR_BADELFFMT;
+ }
+
+ /* Load program header */
+ nbytes = ep->e_phnum * sizeof(Elf32_Phdr);
+ phtab = (Elf32_Phdr *) KMALLOC(nbytes,0);
+ if (!phtab) {
+ return CFE_ERR_NOMEM;
+ }
+
+ if (fs_seek(fsctx,ref,ep->e_phoff,FILE_SEEK_BEGINNING) != ep->e_phoff ||
+ fs_read(fsctx,ref,(uint8_t *)phtab,nbytes) != nbytes) {
+ KFREE(phtab);
+ return CFE_ERR_IOERR;
+ }
+
+ /*
+ * From now on we've got no guarantee about the file order,
+ * even where the section header is. Hopefully most linkers
+ * will put the section header after the program header, when
+ * they know that the executable is not demand paged. We assume
+ * that the symbol and string tables always follow the program
+ * segments.
+ */
+
+ /* read section table (if before first program segment) */
+ if (ep->e_shoff < phtab[0].p_offset) {
+ shtab = elfgetshdr(fsctx,ref,ep);
+ }
+
+ /* load program segments */
+ /* We cope with a badly sorted program header, as produced by
+ * older versions of the GNU linker, by loading the segments
+ * in file offset order, not in program header order. */
+
+ while (1) {
+ Elf32_Off lowest_offset = ~0;
+ Elf32_Phdr *ph = 0;
+
+ /* find nearest loadable segment */
+ for (i = 0; i < ep->e_phnum; i++)
+ if ((phtab[i].p_type == PT_LOAD) && (phtab[i].p_offset < lowest_offset)) {
+ ph = &phtab[i];
+ lowest_offset = ph->p_offset;
+ }
+ if (!ph) {
+ break; /* none found, finished */
+ }
+
+ /* load the segment */
+ if (ph->p_filesz) {
+ if (fs_seek(fsctx,ref,ph->p_offset,FILE_SEEK_BEGINNING) != ph->p_offset) {
+ if (shtab) KFREE(shtab);
+ KFREE(phtab);
+ return CFE_ERR_BADELFFMT;
+ }
+ res = readprogsegment(fsctx,ref,
+ (void *)(intptr_t)(signed)ph->p_vaddr,
+ ph->p_filesz,flags);
+ if (res != ph->p_filesz) {
+ if (shtab) KFREE(shtab);
+ KFREE(phtab);
+ return res;
+ }
+ }
+
+ if (ph->p_filesz < ph->p_memsz) {
+ res = readclearbss((void *)(intptr_t)(signed)ph->p_vaddr + ph->p_filesz,
+ ph->p_memsz - ph->p_filesz,flags);
+ if (res < 0) {
+ if (shtab) KFREE(shtab);
+ KFREE(phtab);
+ return res;
+ }
+ }
+
+ ph->p_type = PT_NULL; /* remove from consideration */
+ }
+
+ KFREE(phtab);
+
+ *entrypt = (intptr_t)(signed)ep->e_entry; /* return entry point */
+ return 0;
+}
+
+
+
+/* *********************************************************************
+ * cfe_elfload(ops,file,flags)
+ *
+ * Read an ELF file (main entry point)
+ *
+ * Input parameters:
+ * ops - fileio dispatch
+ * file - name of file to read
+ * ept - where to put entry point
+ * flags - load flags
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+static int cfe_elfload(cfe_loadargs_t *la)
+{
+ fileio_ctx_t *fsctx;
+ void *ref;
+ int res;
+
+ /*
+ * Look up the file system type and get a context
+ */
+
+
+ res = fs_init(la->la_filesys,&fsctx,la->la_device);
+ if (res != 0) {
+ return res;
+ }
+
+ /*
+ * Turn on compression if we're doing that.
+ */
+
+ if (la->la_flags & LOADFLG_COMPRESSED) {
+ res = fs_hook(fsctx,"z");
+ if (res != 0) {
+ return res;
+ }
+ }
+
+ /*
+ * Open the remote file
+ */
+
+ res = fs_open(fsctx,&ref,la->la_filename,FILE_MODE_READ);
+ if (res != 0) {
+ fs_uninit(fsctx);
+ return CFE_ERR_FILENOTFOUND;
+ }
+
+ /*
+ * Load the image.
+ */
+
+ la->la_entrypt = 0;
+ res = elfload_internal(fsctx,ref,&(la->la_entrypt),la->la_flags);
+
+ /*
+ * All done, release resources
+ */
+
+ fs_close(fsctx,ref);
+ fs_uninit(fsctx);
+
+ return res;
+}
+
+
diff --git a/cfe/cfe/main/cfe_ldr_raw.c b/cfe/cfe/main/cfe_ldr_raw.c
new file mode 100644
index 0000000..d436849
--- /dev/null
+++ b/cfe/cfe/main/cfe_ldr_raw.c
@@ -0,0 +1,360 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * RAW Program Loader File: cfe_ldr_raw.c
+ *
+ * This program reads raw binaries into memory.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_error.h"
+#include "cfe_devfuncs.h"
+
+#include "cfe.h"
+#include "cfe_fileops.h"
+
+#include "cfe_boot.h"
+#include "cfe_bootblock.h"
+
+#include "cfe_loader.h"
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+static int cfe_rawload(cfe_loadargs_t *la);
+
+const cfe_loader_t rawloader = {
+ "raw",
+ cfe_rawload,
+ 0};
+
+/* *********************************************************************
+ * cfe_findbootblock(la,fsctx,ref)
+ *
+ * Find the boot block on the specified device.
+ *
+ * Input parameters:
+ * la - loader args (to be filled in)
+ * ops - file operations
+ * ref - reference for open file handle
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+static int cfe_findbootblock(cfe_loadargs_t *la,
+ fileio_ctx_t *fsctx,
+ void *ref,
+ struct boot_block *bootblock)
+{
+ uint32_t checksum = 0;
+ uint32_t calcsum;
+ uint32_t secsize = 0;
+ uint64_t secoffset = 0;
+ int res;
+ int curblk;
+
+ /*
+ * Search for the boot block. Stop when we find
+ * something with a matching checksum and magic
+ * number.
+ */
+
+ fs_seek(fsctx,ref,0,FILE_SEEK_BEGINNING);
+
+ for (curblk = 0; curblk < BOOT_BLOCK_MAXLOC; curblk++) {
+
+
+ /* Read a block */
+
+ res = fs_read(fsctx,ref,
+ (unsigned char *) bootblock,
+ sizeof(struct boot_block));
+
+ if (res != sizeof(struct boot_block)) {
+ return CFE_ERR_IOERR;
+ }
+
+ /* Verify magic number */
+
+ if (bootblock->bb_magic != BOOT_MAGIC_NUMBER) {
+ continue;
+ }
+
+ /* Extract fields from block */
+
+ checksum = ((uint32_t) (bootblock->bb_hdrinfo & BOOT_HDR_CHECKSUM_MASK));
+ bootblock->bb_hdrinfo &= ~BOOT_HDR_CHECKSUM_MASK;
+ secsize = ((uint32_t) (bootblock->bb_secsize & BOOT_SECSIZE_MASK));
+ secoffset = bootblock->bb_secstart;
+
+ /* Verify block's checksum */
+
+ CHECKSUM_BOOT_DATA(&(bootblock->bb_magic),BOOT_BLOCK_SIZE,&calcsum);
+
+ if (checksum == calcsum) {
+ break;
+ }
+ }
+
+ /*
+ * Okay, determine if we were successful.
+ */
+
+ if (bootblock->bb_magic != BOOT_MAGIC_NUMBER) {
+ return CFE_ERR_INVBOOTBLOCK;
+ }
+
+ if (checksum != calcsum) {
+ return CFE_ERR_BBCHECKSUM;
+ }
+
+ /*
+ * If we get here, we had a valid boot block.
+ */
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * cfe_rawload(la)
+ *
+ * Read a raw (unformatted) boot file
+ *
+ * Input parameters:
+ * la - loader args
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+static int cfe_rawload(cfe_loadargs_t *la)
+{
+ int res;
+ fileio_ctx_t *fsctx;
+ const fileio_dispatch_t *ops;
+ void *ref;
+ int ttlcopy = 0;
+ int findbb;
+ int devinfo;
+ struct boot_block bootblock;
+ uint8_t *ptr;
+ uint8_t *bootcode;
+ uint32_t checksum,calcsum;
+ uint64_t secoffset = 0;
+ int32_t maxsize;
+ int amtcopy;
+ int thisamt;
+ uint32_t loadflags;
+ int onedot;
+
+ loadflags = la->la_flags;
+
+ /*
+ * Set starting address and maximum size. You can either
+ * explicitly set this (with LOADFLG_SPECADDR) or
+ * let CFE decide. If CFE decides, the load address
+ * will be BOOT_START_ADDRESS in all cases.
+ * The size is dependant on the device type: block and flash
+ * devices will get this info from the boot block,
+ * and network devices will get the info by reaching EOF
+ * on reads, up to the maximum size of the boot area.
+ */
+
+ if (loadflags & LOADFLG_SPECADDR) {
+ bootcode = (uint8_t *) la->la_address;
+ maxsize = la->la_maxsize;
+ findbb = FALSE; /* don't find a boot block */
+ }
+ else {
+ bootcode = (uint8_t *) BOOT_START_ADDRESS;
+ maxsize = BOOT_AREA_SIZE;
+ findbb = FALSE;
+ devinfo = la->la_device ? cfe_getdevinfo(la->la_device) : 0;
+
+ /*
+ * If the device is either a disk or a flash device,
+ * we will expect to find a boot block.
+ * Serial and network devices do not have boot blocks.
+ */
+ if ((devinfo >= 0) &&
+ ( ((devinfo & CFE_DEV_MASK) == CFE_DEV_DISK) ||
+ ((devinfo & CFE_DEV_MASK) == CFE_DEV_FLASH) )) {
+ findbb = TRUE;
+ }
+ }
+
+
+ /*
+ * merge in any filesystem-specific flags
+ */
+
+ ops = cfe_findfilesys(la->la_filesys);
+ if (!ops) return CFE_ERR_FSNOTAVAIL;
+ loadflags |= ops->loadflags;
+
+ /*
+ * turn off the boot block if requested.
+ */
+
+ if (loadflags & LOADFLG_NOBB) findbb = FALSE;
+
+ /*
+ * Create a file system context
+ */
+
+ res = fs_init(la->la_filesys,&fsctx,la->la_device);
+ if (res != 0) {
+ return res;
+ }
+
+ /*
+ * Turn on compression if we're doing that.
+ */
+
+ if (!findbb && (la->la_flags & LOADFLG_COMPRESSED)) {
+ res = fs_hook(fsctx,"z");
+ if (res != 0) {
+ return res;
+ }
+ }
+
+ /*
+ * Open the boot device
+ */
+
+ res = fs_open(fsctx,&ref,la->la_filename,FILE_MODE_READ);
+ if (res != 0) {
+ fs_uninit(fsctx);
+ return res;
+ }
+
+ /*
+ * If we need to find a boot block, do it now.
+ */
+
+ if (findbb) {
+ res = cfe_findbootblock(la,fsctx,ref,&bootblock);
+
+ /*
+ * If we found the boot block, seek to the part of the
+ * disk where the boot code is.
+ * Otherwise, get out now, since the disk has no boot block.
+ */
+
+ if (res == 0) {
+ maxsize = (int) ((uint32_t) (bootblock.bb_secsize & BOOT_SECSIZE_MASK));
+ secoffset = bootblock.bb_secstart;
+ fs_seek(fsctx,ref,secoffset,FILE_SEEK_BEGINNING);
+ }
+ else {
+ fs_close(fsctx,ref);
+ fs_uninit(fsctx);
+ return res;
+ }
+
+ }
+
+ /*
+ * Okay, go load the boot file.
+ */
+
+ ptr = bootcode;
+ amtcopy = maxsize;
+ ttlcopy = 0;
+
+ onedot = amtcopy / 10; /* ten dots for entire load */
+ if (onedot < 4096) onedot = 4096; /* but minimum 4096 bytes per dot */
+ onedot = (onedot + 1) & ~4095; /* round to multiple of 4096 */
+
+ while (amtcopy > 0) {
+ thisamt = onedot;
+ if (thisamt > amtcopy) thisamt = amtcopy;
+
+ res = fs_read(fsctx,ref,ptr,thisamt);
+ if (la->la_flags & LOADFLG_NOISY) {
+ xprintf(".");
+ }
+ if (res <= 0) break;
+ ptr += res;
+ amtcopy -= res;
+ ttlcopy += res;
+ }
+
+ /*
+ * We're done with the file.
+ */
+
+ fs_close(fsctx,ref);
+ fs_uninit(fsctx);
+
+ /*
+ * Verify the boot loader checksum if we were reading
+ * the disk.
+ */
+
+ if (findbb) {
+ CHECKSUM_BOOT_DATA(bootcode,maxsize,&calcsum);
+ checksum = (uint32_t) ((bootblock.bb_secsize & BOOT_DATA_CHECKSUM_MASK)
+ >> BOOT_DATA_CHECKSUM_SHIFT);
+
+ if (checksum != calcsum) {
+ return CFE_ERR_BOOTPROGCHKSUM;
+ }
+ }
+
+ la->la_entrypt = (uintptr_t) bootcode;
+
+ if (la->la_flags & LOADFLG_NOISY) xprintf(" %d bytes read\n",ttlcopy);
+
+ return (res < 0) ? res : ttlcopy;
+
+}
+
diff --git a/cfe/cfe/main/cfe_ldr_srec.c b/cfe/cfe/main/cfe_ldr_srec.c
new file mode 100644
index 0000000..b067f2b
--- /dev/null
+++ b/cfe/cfe/main/cfe_ldr_srec.c
@@ -0,0 +1,557 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * SREC Program Loader File: cfe_ldr_srec.c
+ *
+ * This program reads Motorola S-record files into memory
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_error.h"
+#include "cfe_devfuncs.h"
+
+#include "cfe.h"
+#include "cfe_fileops.h"
+
+#include "cfe_boot.h"
+#include "cfe_bootblock.h"
+
+#include "cfe_loader.h"
+
+#include "cfe_mem.h"
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+static int cfe_srecload(cfe_loadargs_t *la);
+
+const cfe_loader_t srecloader = {
+ "srec",
+ cfe_srecload,
+ 0};
+
+
+typedef struct linebuf_s {
+ char linebuf[256];
+ int curidx;
+ int buflen;
+ int eof;
+ void *ref;
+ fileio_ctx_t *fsctx;
+} linebuf_t;
+
+#define initlinebuf(b,r,o) (b)->curidx = 0; (b)->buflen = 0; \
+ (b)->eof = 0 ; (b)->ref = r; (b)->fsctx = o
+
+
+/* *********************************************************************
+ * readchar(file)
+ *
+ * Read a character from a file. It's kind of like getchar
+ * on "C" FILE devices, but not so fancy.
+ *
+ * Input parameters:
+ * file - pointer to a linebuf_t containing reader state
+ *
+ * Return value:
+ * character, or -1 if at EOF
+ ********************************************************************* */
+
+static int readchar(linebuf_t *file)
+{
+ int ch;
+ int res;
+
+ if (file->eof) return -1;
+
+ if (file->curidx == file->buflen) {
+ for (;;) {
+ res = fs_read(file->fsctx,file->ref,file->linebuf,sizeof(file->linebuf));
+ if (res < 0) {
+ file->eof = -1;
+ return -1;
+ }
+ if (res == 0) continue;
+ file->buflen = res;
+ file->curidx = 0;
+ break;
+ }
+ }
+
+ ch = file->linebuf[file->curidx];
+ file->curidx++;
+ return ch;
+}
+
+
+/* *********************************************************************
+ * readline(file,buffer,maxlen)
+ *
+ * Read a line of text from a file using our crude file stream
+ * mechanism.
+ *
+ * Input parameters:
+ * file - pointer to a linebuf_t containing reader state
+ * buffer - will receive line of text
+ * maxlen - number of bytes that will fit in buffer
+ *
+ * Return value:
+ * 0 if ok, else <0 if at EOF
+ ********************************************************************* */
+
+static int readline(linebuf_t *file,char *buffer,int maxlen)
+{
+ int ch;
+ char *ptr;
+
+ ptr = buffer;
+ maxlen--; /* account for terminating null */
+
+ while (maxlen) {
+ ch = readchar(file);
+ if (ch == -1) return -1;
+ if (ch == 27) return -1; /* ESC */
+ if ((ch == '\n') || (ch == '\r')) break;
+ *ptr++ = (char) ch;
+ maxlen--;
+ }
+
+ *ptr = '\0';
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * getxdigit(c)
+ *
+ * Convert a hex digit into its numeric equivalent
+ *
+ * Input parameters:
+ * c - character
+ *
+ * Return value:
+ * value
+ ********************************************************************* */
+
+static int getxdigit(char c)
+{
+ if ((c >= '0') && (c <= '9')) return c - '0';
+ if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10;
+ if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10;
+ return -1;
+}
+
+/* *********************************************************************
+ * getbyte(line)
+ *
+ * Process two hex digits and return the value
+ *
+ * Input parameters:
+ * line - pointer to pointer to characters (updated on exit)
+ *
+ * Return value:
+ * byte value, or <0 if bad hex digits
+ ********************************************************************* */
+
+static int getbyte(char **line)
+{
+ int res;
+ int c1,c2;
+
+ c1 = getxdigit(*(*(line)+0));
+ if (c1 < 0) return -1;
+
+ c2 = getxdigit(*(*(line)+1));
+ if (c2 < 0) return -1;
+
+ res = (c1*16+c2);
+ (*line) += 2;
+
+ return res;
+}
+
+
+/* *********************************************************************
+ * procsrec(line,loadaddr,blklen,data)
+ *
+ * Process an S-record, reading the data into a local buffer
+ * and returning the block's address.
+ *
+ * Input parameters:
+ * line - line of text (s-record line)
+ * loadaddr - will be filled with address where data should go
+ * blklen - will be filled in with size of record
+ * data - points to buffer to receive data
+ *
+ * Return value:
+ * <0 if error occured (not an s-record)
+ ********************************************************************* */
+
+static int procsrec(char *line,
+ unsigned int *loadaddr,
+ unsigned int *blklen,
+ unsigned char *data)
+{
+ char rectype;
+ unsigned char b;
+ unsigned int len;
+ unsigned int minlen;
+ unsigned int linelen;
+ unsigned int addr;
+ unsigned int chksum;
+
+ int idx;
+ int ret = 0;
+
+ addr = 0;
+
+ if (*line++ != 'S')
+ return -1; /* not an S record */
+
+ rectype = *line++;
+
+ minlen = 3; /* type 1 record */
+ switch (rectype) {
+ case '0':
+ break;
+
+ /*
+ * data bytes
+ */
+ case '3':
+ minlen++;
+ /* fall through */
+ case '2':
+ minlen++;
+ /* fall through */
+ case '1':
+ chksum = 0;
+ linelen = getbyte(&line);
+ if (linelen < minlen) {
+ xprintf("srec: line too short\n");
+ return -1;
+ }
+ chksum += (unsigned int)linelen;
+
+ /*
+ * There are two address bytes in a type 1 record, and three
+ * in a type 2 record. The high-order byte is first, then
+ * one or two lower-order bytes. Build up the adddress.
+ */
+ b = getbyte(&line);
+ chksum += (unsigned int)b;
+ addr = b;
+ b = getbyte(&line);
+ chksum += (unsigned int)b;
+ addr <<= 8;
+ addr += b;
+ if (rectype == '2') {
+ b = getbyte(&line);
+ chksum += (unsigned int)b;
+ addr <<= 8;
+ addr += b;
+ }
+ if (rectype == '3') {
+ b = getbyte(&line);
+ chksum += (unsigned int)b;
+ addr <<= 8;
+ addr += b;
+ b = getbyte(&line);
+ chksum += (unsigned int)b;
+ addr <<= 8;
+ addr += b;
+ }
+
+#if VERBOSE
+ printf("Addr: %08X Len: %3u(0x%x)\n", addr , linelen - minlen,
+ linelen-minlen);
+#endif
+
+ *loadaddr = addr;
+ len = linelen - minlen;
+ *blklen = len;
+
+ for (idx = 0; idx < len; idx++) {
+ b = getbyte(&line);
+ chksum += (unsigned int) b;
+ data[idx] = (unsigned char ) b;
+ }
+
+ b = getbyte(&line);
+ chksum = (~chksum) & 0x000000FF;
+ if (chksum != b) {
+ xprintf("Checksum error in s-record file\n");
+ return -1;
+ }
+ ret = 1;
+ break;
+
+ case '9':
+ linelen = getbyte(&line);
+ b = getbyte(&line);
+ addr = b;
+ b = getbyte(&line);
+ addr <<= 8;
+ addr += b;
+ *loadaddr = addr;
+ ret = -2;
+ break;
+
+ case '8':
+ linelen = getbyte(&line);
+ b = getbyte(&line);
+ addr = b;
+ b = getbyte(&line);
+ addr <<= 8;
+ addr += b;
+ b = getbyte(&line);
+ addr <<= 8;
+ addr += b;
+ *loadaddr = addr;
+ ret = -2;
+ break;
+
+ case '7':
+ linelen = getbyte(&line);
+ b = getbyte(&line);
+ addr = b;
+ b = getbyte(&line);
+ addr <<= 8;
+ addr += b;
+ b = getbyte(&line);
+ addr <<= 8;
+ addr += b;
+ b = getbyte(&line);
+ addr <<= 8;
+ addr += b;
+ *loadaddr = addr;
+ ret = -2;
+ break;
+
+ default:
+ xprintf("Unknown S-record type: %c\n",rectype);
+ return -1;
+ break;
+ }
+
+ return ret;
+}
+
+
+/* *********************************************************************
+ * cfe_srecload(la)
+ *
+ * Read an s-record file
+ *
+ * Input parameters:
+ * la - loader args
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+static int cfe_srecload(cfe_loadargs_t *la)
+{
+ int res;
+ fileio_ctx_t *fsctx;
+ void *ref;
+ int devinfo;
+ int serial = FALSE;
+ unsigned int loadaddr;
+ unsigned int blklen;
+ linebuf_t lb;
+ char line[256];
+ uint8_t data[256];
+ int cnt;
+ unsigned int specaddr; /* current address if loading to a special address */
+ int specflg; /* true if in "special address" mode */
+ int firstrec = 1; /* true if we have not seen the first record */
+
+ /*
+ * We might want to know something about the boot device.
+ */
+
+ devinfo = la->la_device ? cfe_getdevinfo(la->la_device) : 0;
+
+ /*
+ * Figure out if we're loading to a "special address". This lets
+ * us load S-records into a temporary buffer, ignoring the
+ * addresses in the records (but using them so we'll know where
+ * they go relative to each other
+ */
+
+ specflg = (la->la_flags & LOADFLG_SPECADDR) ? 1 : 0;
+ specaddr = 0;
+
+ /*
+ * If the device is a serial port, we want to know that.
+ */
+
+ if ((devinfo >= 0) &&
+ ((devinfo & CFE_DEV_MASK) == CFE_DEV_SERIAL)) {
+ serial = TRUE;
+ }
+
+ /*
+ * Create a file system context
+ */
+
+ res = fs_init(la->la_filesys,&fsctx,la->la_device);
+ if (res != 0) {
+ return res;
+ }
+
+ /*
+ * Turn on compression if we're doing that.
+ */
+
+ if (la->la_flags & LOADFLG_COMPRESSED) {
+ res = fs_hook(fsctx,"z");
+ if (res != 0) {
+ return res;
+ }
+ }
+
+ /*
+ * Open the boot device
+ */
+
+ res = fs_open(fsctx,&ref,la->la_filename,FILE_MODE_READ);
+ if (res != 0) {
+ fs_uninit(fsctx);
+ return res;
+ }
+
+ /*
+ * Okay, go load the boot file. Process S-records until
+ * we get an entry point record (usually at the end).
+ *
+ * XXX what if it's *not* at the end?
+ */
+
+ initlinebuf(&lb,ref,fsctx);
+
+ cnt = 0;
+ for (;;) {
+ /*
+ * Read a line of text
+ */
+ res = readline(&lb,line,sizeof(line));
+ if (res < 0) break; /* reached EOF */
+
+ /*
+ * Process the S-record. If at EOF, procsrec returns 0.
+ * Invalid s-records returns -1.
+ */
+
+ if (line[0] == 0) continue;
+
+ res = procsrec(line,&loadaddr,&blklen,data);
+
+#if 0
+ if (res == -2 || res >= 0)
+ xprintf(".");
+#endif
+ if (res < 0) break;
+
+ /*
+ * Handle "special address" mode. All S-records will be
+ * loaded into a buffer passed by the caller to the loader.
+ * We use the addresses in the S-records to determine
+ * relative placement of the data, keying on the first
+ * S-record in the file.
+ */
+
+ if ((res == 1) && (specflg)) {
+ if (firstrec) {
+ /* First S-record seen sets the base for all that follow */
+ specaddr = loadaddr;
+ firstrec = 0;
+ }
+ loadaddr = la->la_address + (intptr_t) (loadaddr - specaddr);
+ }
+
+ cnt++;
+
+ if (res == 1) {
+ if (!cfe_arena_loadcheck((intptr_t) loadaddr,blklen)) {
+ xprintf("Invalid address: %P\n",loadaddr);
+ res = -1;
+ break;
+ }
+ memcpy((uint8_t *) (intptr_t) (signed)loadaddr,data,blklen);
+ }
+ }
+
+ /*
+ * We're done with the file.
+ */
+
+ fs_close(fsctx,ref);
+ fs_uninit(fsctx);
+
+ /*
+ * Say something cute on the LEDs.
+ * Don't do this for every s-record, because if logging the LED
+ * changes out the serial port, that can take a Long Time. Just
+ * goes to show: too much cuteness is a _very_ bad thing.
+ */
+ xsprintf(line,"%04d",cnt);
+ cfe_ledstr(line);
+
+ if (res == -2) {
+ la->la_entrypt = (intptr_t) (signed) loadaddr;
+ res = 0;
+ }
+
+ return res;
+}
+
+
diff --git a/cfe/cfe/main/cfe_link.mk b/cfe/cfe/main/cfe_link.mk
new file mode 100644
index 0000000..7529dc4
--- /dev/null
+++ b/cfe/cfe/main/cfe_link.mk
@@ -0,0 +1,26 @@
+#
+# This Makefile snippet takes care of linking the firmware.
+#
+
+pci : $(PCICOMMON) $(PCIMACHDEP)
+ echo done
+
+cfe cfe.bin : $(CRT0OBJS) $(BSPOBJS) $(LIBCFE)
+ $(GLD) -o cfe -Map cfe.map $(LDFLAGS) $(CRT0OBJS) $(BSPOBJS) -L. -lcfe $(LDLIBS)
+ $(OBJDUMP) -d cfe > cfe.dis
+ $(OBJCOPY) --output-target=binary cfe cfe.bin
+ $(OBJCOPY) --input-target=binary --output-target=srec cfe.bin cfe.srec
+
+cfe.flash : cfe.bin mkflashimage
+ ./mkflashimage -v ${ENDIAN} -B ${CFG_BOARDNAME} -V ${CFE_VER_MAJ}.${CFE_VER_MIN}.${CFE_VER_ECO} cfe.bin cfe.flash
+ $(OBJCOPY) --input-target=binary --output-target=srec cfe.flash cfe.flash.srec
+
+
+clean :
+ rm -f *.o *~ cfe cfe.bin cfe.dis cfe.map cfe.srec
+ rm -f makereg ${CPU}_socregs.inc mkpcidb pcidevs_data2.h mkflashimage
+ rm -f build_date.c
+ rm -f libcfe.a
+ rm -f cfe.flash cfe.flash.srec $(CLEANOBJS)
+
+distclean : clean
diff --git a/cfe/cfe/main/cfe_loader.c b/cfe/cfe/main/cfe_loader.c
new file mode 100644
index 0000000..bbd3eb4
--- /dev/null
+++ b/cfe/cfe/main/cfe_loader.c
@@ -0,0 +1,135 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Loader API File: cfe_loader.c
+ *
+ * This is the main API for the program loader. CFE supports
+ * multiple "installable" methods for loading programs, allowing
+ * us to deal with a variety of methods for moving programs
+ * into memory for execution.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+
+#include "cfe_error.h"
+
+#include "cfe.h"
+#include "cfe_fileops.h"
+
+#include "cfe_loader.h"
+
+#include "bsp_config.h"
+
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+extern const cfe_loader_t elfloader;
+extern const cfe_loader_t rawloader;
+extern const cfe_loader_t srecloader;
+
+/* *********************************************************************
+ * Loader list
+ ********************************************************************* */
+
+const cfe_loader_t * const cfe_loaders[] = {
+ &elfloader,
+#if !CFG_MINIMAL_SIZE
+ &rawloader,
+ &srecloader,
+#endif
+ NULL};
+
+/* *********************************************************************
+ * cfe_findloader(name)
+ *
+ * Find a loader by name
+ *
+ * Input parameters:
+ * name - name of loader to find
+ *
+ * Return value:
+ * pointer to loader structure or NULL
+ ********************************************************************* */
+
+const cfe_loader_t *cfe_findloader(char *name)
+{
+ const cfe_loader_t * const *ldr;
+
+ ldr = cfe_loaders;
+
+ while (*ldr) {
+ if (strcmp(name,(*ldr)->name) == 0) return (*ldr);
+ ldr++;
+ }
+
+ return NULL;
+}
+
+
+/* *********************************************************************
+ * cfe_load_progam(name,args)
+ *
+ * Look up a loader and call it.
+ *
+ * Input parameters:
+ * name - name of loader to run
+ * args - arguments to pass
+ *
+ * Return value:
+ * return value
+ ********************************************************************* */
+
+int cfe_load_program(char *name,cfe_loadargs_t *la)
+{
+ const cfe_loader_t *ldr;
+ int res;
+
+ ldr = cfe_findloader(name);
+ if (!ldr) return CFE_ERR_LDRNOTAVAIL;
+
+ res = LDRLOAD(ldr,la);
+
+ return res;
+}
diff --git a/cfe/cfe/main/cfe_main.c b/cfe/cfe/main/cfe_main.c
new file mode 100644
index 0000000..1a451a6
--- /dev/null
+++ b/cfe/cfe/main/cfe_main.c
@@ -0,0 +1,636 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Main Module File: cfe_main.c
+ *
+ * This module contains the main "C" routine for CFE and
+ * the main processing loop. There should not be any board-specific
+ * stuff in here.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_timer.h"
+
+#include "env_subr.h"
+#include "ui_command.h"
+#include "cfe_mem.h"
+#include "cfe.h"
+
+#include "exception.h"
+
+#include "bsp_config.h"
+
+#include "segtable.h"
+
+#include "initdata.h"
+
+#if CFG_PCI
+#include "pcivar.h"
+#endif
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#ifndef CFG_STACK_SIZE
+#define STACK_SIZE 8192
+#else
+#define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023)
+#endif
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+void cfe_main(int,int);
+extern void cfe_device_poll(void *x);
+
+extern int ui_init_envcmds(void);
+extern int ui_init_devcmds(void);
+extern int ui_init_netcmds(void);
+extern int ui_init_memcmds(void);
+extern int ui_init_loadcmds(void);
+extern int ui_init_pcicmds(void);
+extern int ui_init_examcmds(void);
+extern int ui_init_flashcmds(void);
+extern int ui_init_misccmds(void);
+#if CFG_VAPI
+extern int ui_init_vapicmds(void);
+#endif
+
+#if CFG_VENDOR_EXTENSIONS
+extern int ui_init_vendorcmds(void);
+#endif
+
+void cfe_command_restart(uint64_t status);
+
+extern segtable_t *_getsegtbl(void);
+
+extern const char *builddate;
+extern const char *builduser;
+
+#if CFG_MULTI_CPUS
+extern int altcpu_cmd_start(uint64_t,uint64_t *);
+extern int altcpu_cmd_stop(uint64_t);
+#endif
+
+
+
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+const char *cfe_boardname = CFG_BOARDNAME;
+unsigned int cfe_startflags =
+#if CFG_PCI
+ CFE_INIT_PCI |
+#endif
+ 0;
+
+/* *********************************************************************
+ * cfe_setup_default_env()
+ *
+ * Initialize the default environment for CFE. These are all
+ * the temporary variables that do not get stored in the NVRAM
+ * but are available to other programs and command-line macros.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void cfe_setup_default_env(void)
+{
+ char buffer[80];
+
+ xsprintf(buffer,"%d.%d.%d",CFE_VER_MAJOR,CFE_VER_MINOR,CFE_VER_BUILD);
+ env_setenv("CFE_VERSION",buffer,ENV_FLG_BUILTIN | ENV_FLG_READONLY);
+
+ if (cfe_boardname) {
+ env_setenv("CFE_BOARDNAME",(char *) cfe_boardname,
+ ENV_FLG_BUILTIN | ENV_FLG_READONLY);
+ }
+
+ xsprintf(buffer,"%d",mem_totalsize);
+ env_setenv("CFE_MEMORYSIZE",buffer,ENV_FLG_BUILTIN | ENV_FLG_READONLY);
+
+}
+
+
+/* *********************************************************************
+ * cfe_init_ui()
+ *
+ * Call all the other UI initialization modules. Each of these
+ * modules usually calls back to the UI dispatcher to add command
+ * tables.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+#if CFG_MINIMAL_SIZE
+#define OPTIONAL(x)
+#else
+#define OPTIONAL(x) x
+#endif
+
+static void cfe_init_ui(void)
+{
+ ui_init_cmddisp();
+
+ ui_init_envcmds();
+ OPTIONAL(ui_init_devcmds());
+#if CFG_NETWORK
+ ui_init_netcmds();
+#endif
+ ui_init_loadcmds();
+ OPTIONAL(ui_init_memcmds());
+
+#if CFG_PCI
+ ui_init_pcicmds();
+#endif
+ OPTIONAL(ui_init_examcmds());
+ ui_init_flashcmds();
+#if CFG_VAPI
+ ui_init_vapicmds();
+#endif
+
+#if CFG_VENDOR_EXTENSIONS
+ ui_init_vendorcmds();
+#endif
+
+ OPTIONAL(ui_init_misccmds());
+
+}
+
+
+/* *********************************************************************
+ * cfe_ledstr(leds)
+ *
+ * Display a string on the board's LED display, if it has one.
+ * This routine depends on the board-support package to
+ * include a "driver" to write to the actual LED, if the board
+ * does not have one this routine will do nothing.
+ *
+ * The LEDs are written at various places in the initialization
+ * sequence, to debug board problems.
+ *
+ * Input parameters:
+ * leds - pointer to four-character ASCII string
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_ledstr(const char *leds)
+{
+ unsigned int val;
+
+ val = ((((unsigned int) leds[0]) << 24) |
+ (((unsigned int) leds[1]) << 16) |
+ (((unsigned int) leds[2]) << 8) |
+ ((unsigned int) leds[3]));
+
+ cfe_leds(val);
+}
+
+
+/* *********************************************************************
+ * cfe_say_hello()
+ *
+ * Print out the CFE startup message and copyright notice
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+static void cfe_say_hello(void)
+{
+ xprintf("\n\n");
+ xprintf("CFE version 2.0.2"
+#ifdef CFE_VER_RELEASE
+ ".%d"
+#endif
+ " for DGN2200v2 (%s)\n",
+ //CFE_VER_MAJOR,CFE_VER_MINOR,CFE_VER_BUILD,
+#ifdef CFE_VER_RELEASE
+ CFE_VER_RELEASE,
+#endif
+ //cfe_boardname,
+#ifdef __long64
+ "64bit,"
+#else
+ "32bit,"
+#endif
+#if CFG_MULTI_CPUS
+ "MP,"
+#else
+ "SP,"
+#endif
+#ifdef __MIPSEL
+ "LE"
+#endif
+#ifdef __MIPSEB
+ "BE"
+#endif
+#if CFG_VAPI
+ ",VAPI"
+#endif
+ );
+
+ xprintf("Build Date: %s (%s)\n",builddate,builduser);
+ xprintf("Copyright (C) 2000,2001,2002,2003 Broadcom Corporation.\n");
+ xprintf("\n");
+}
+
+
+/* *********************************************************************
+ * cfe_restart()
+ *
+ * Restart CFE from scratch, jumping back to the boot vector.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+void cfe_restart(void)
+{
+ _exc_restart();
+}
+
+
+/* *********************************************************************
+ * cfe_start(ept)
+ *
+ * Start a user program
+ *
+ * Input parameters:
+ * ept - entry point
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+void cfe_start(unsigned long ept)
+{
+ SETLEDS("RUN!");
+ cfe_launch(ept);
+}
+
+
+/* *********************************************************************
+ * cfe_startup_info()
+ *
+ * Display startup memory configuration messages
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void cfe_startup_info(void)
+{
+ segtable_t *segtbl;
+
+ segtbl = _getsegtbl();
+ xprintf("CPU type 0x%X: ",(uint32_t)cpu_prid);
+ if (cfe_cpu_speed < 1000000) xprintf("%dKHz\n",cfe_cpu_speed/1000);
+ else xprintf("%dMHz\n",cfe_cpu_speed/1000000);
+ xprintf("Total memory: 0x%llX bytes (%dMB)\n",
+ (((uint64_t)mem_totalsize) << 20),(uint32_t)mem_totalsize);
+
+ xprintf("\n");
+ xprintf("Total memory used by CFE: 0x%08X - 0x%08X (%d)\n",
+ (uint32_t) mem_bottomofmem,
+ (uint32_t) mem_topofmem,
+ (uint32_t) mem_topofmem-mem_bottomofmem);
+ xprintf("Initialized Data: 0x%08X - 0x%08X (%d)\n",
+ (uint32_t) (segtbl[R_SEG_FDATA] + mem_datareloc),
+ (uint32_t) (segtbl[R_SEG_EDATA] + mem_datareloc),
+ (uint32_t) (segtbl[R_SEG_EDATA] - segtbl[R_SEG_FDATA]));
+ xprintf("BSS Area: 0x%08X - 0x%08X (%d)\n",
+ (uint32_t) (segtbl[R_SEG_FBSS] + mem_datareloc),
+ (uint32_t) (segtbl[R_SEG_END] + mem_datareloc),
+ (uint32_t) (segtbl[R_SEG_END] - segtbl[R_SEG_FBSS]));
+ xprintf("Local Heap: 0x%08X - 0x%08X (%d)\n",
+ (uint32_t)(mem_heapstart),
+ (uint32_t)(mem_heapstart + (CFG_HEAP_SIZE*1024)),
+ (CFG_HEAP_SIZE*1024));
+ xprintf("Stack Area: 0x%08X - 0x%08X (%d)\n",
+ (uint32_t)(mem_heapstart + (CFG_HEAP_SIZE*1024)),
+ (uint32_t)(mem_heapstart + (CFG_HEAP_SIZE*1024) + STACK_SIZE),
+ STACK_SIZE);
+ xprintf("Text (code) segment: 0x%08X - 0x%08X (%d)\n",
+ (uint32_t)mem_textbase,
+ (uint32_t)(mem_textbase+mem_textsize),
+ (uint32_t) mem_textsize);
+ xprintf("Boot area (physical): 0x%08X - 0x%08X\n",
+ mem_bootarea_start,mem_bootarea_start+mem_bootarea_size);
+ xprintf("Relocation Factor: I:%08X - D:%08X\n",
+ (uint32_t) mem_textreloc,(uint32_t) mem_datareloc);
+
+}
+
+
+/* *********************************************************************
+ * cfe_autostart()
+ *
+ * Process automatic commands at startup
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void cfe_autostart(void)
+{
+ char *env;
+ int noauto = 0;
+ char ch;
+
+ env = env_getenv("STARTUP");
+ if (!env) return;
+
+ while (console_status()) {
+ console_read(&ch,1);
+ if (ch == 3) noauto = TRUE; /* Ctrl-C means no auto */
+ }
+
+ if (noauto) {
+ xprintf("Automatic startup canceled via Ctrl-C\n");
+ return;
+ }
+
+ ui_docommands(env);
+}
+
+/* *********************************************************************
+ * cfe_main(a,b)
+ *
+ * It's gotta start somewhere.
+ *
+ * Input parameters:
+ * a,b - not used
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+void cfe_main(int a,int b)
+{
+
+ /*
+ * By the time this routine is called, the following things have
+ * already been done:
+ *
+ * 1. The processor(s) is(are) initialized.
+ * 2. The caches are initialized.
+ * 3. The memory controller is initialized.
+ * 4. BSS has been zeroed.
+ * 5. The data has been moved to R/W space.
+ * 6. The "C" Stack has been initialized.
+ */
+
+ cfe_bg_init(); /* init background processing */
+ cfe_attach_init();
+ cfe_timer_init(); /* Timer process */
+ cfe_bg_add(cfe_device_poll,NULL);
+
+ /*
+ * Initialize the memory allocator
+ */
+
+ SETLEDS("KMEM");
+ KMEMINIT((unsigned char *) (uintptr_t) mem_heapstart,
+ ((CFG_HEAP_SIZE)*1024));
+
+ /*
+ * Initialize the console. It is done before the other devices
+ * get turned on. The console init also sets the variable that
+ * contains the CPU speed.
+ */
+
+ SETLEDS("CONS");
+ board_console_init();
+
+ /*
+ * Set up the exception vectors
+ */
+
+ cfe_setup_exceptions();
+
+ /*
+ * Say hello.
+ */
+
+ SETLEDS("CIOK");
+ cfe_say_hello();
+
+ /*
+ * Initialize the other devices.
+ */
+
+ SETLEDS("AREN");
+ xprintf("Initializing Arena.\n");
+ cfe_arena_init();
+
+#if CFG_PCI
+ if (cfe_startflags & CFE_INIT_PCI) {
+ pci_flags_t flags = PCI_FLG_NORMAL | PCI_FLG_LDT_PREFETCH;
+ char *str;
+ extern cons_t pci_optnames[];
+
+ flags = PCI_FLG_NORMAL | PCI_FLG_LDT_PREFETCH;
+#if CFG_LDT_REV_017
+ flags |= PCI_FLG_LDT_REV_017;
+#endif
+ str = env_getenv("PCI_OPTIONS");
+ setoptions(pci_optnames,str,&flags);
+
+ xprintf("Initializing PCI. [%s]\n",str ? str : "normal");
+ pci_configure(flags);
+ }
+#endif
+
+ SETLEDS("DEVI");
+ xprintf("Initializing Devices.\n");
+ board_device_init();
+
+ cfe_startup_info();
+ SETLEDS("ENVI");
+ cfe_setup_default_env();
+
+ xprintf("\n");
+
+ cfe_init_ui();
+
+ board_final_init();
+
+ cfe_autostart();
+
+ cfe_command_loop();
+}
+
+/* *********************************************************************
+ * cfe_command_restart()
+ *
+ * This routine is called when an application wants to restart
+ * the firmware's command processor. Reopen the console and
+ * jump back into the command loop.
+ *
+ * Input parameters:
+ * status - A0 value of program returning to firmware
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+void cfe_command_restart(uint64_t status)
+{
+ /*
+ * Stop alternate CPU(s). If they're already stopped, this
+ * command will make sure they're stopped.
+ */
+
+#if CFG_MULTI_CPUS
+ altcpu_cmd_stop(1); /* stop CPU 1 (XXX more CPUs?) */
+#endif
+
+ /*
+ * Call board reset functions
+ */
+ board_device_reset();
+
+ /*
+ * Reset devices
+ */
+ cfe_device_reset();
+
+ /*
+ * Reset timers
+ */
+ cfe_timer_init();
+
+ /*
+ * Reopen console
+ */
+ console_open(console_name);
+
+ /*
+ * Display program return status
+ */
+
+ xprintf("*** program exit status = %d\n", (int)status);
+
+ /*
+ * Back to processing user commands
+ */
+ cfe_command_loop();
+}
+
+
+
+/* *********************************************************************
+ * cfe_command_loop()
+ *
+ * This routine reads and processes user commands
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+void cfe_command_loop()
+{
+ char buffer[300];
+ int status;
+ char *prompt;
+
+ SETLEDS("CFE ");
+
+ for (;;) {
+ prompt = env_getenv("PROMPT");
+#if CFG_RAMAPP
+ SETLEDS("CFE*");
+ if (!prompt) prompt = "CFE_RAM> ";
+#else
+ if (!prompt) prompt = "CFE> ";
+#endif
+ console_readline(prompt,buffer,sizeof(buffer));
+
+ status = ui_docommands(buffer);
+
+ if (status != CMD_ERR_BLANK) {
+ xprintf("*** command status = %d\n", status);
+ }
+ }
+}
+
+
+
+
+
diff --git a/cfe/cfe/main/cfe_mem.c b/cfe/cfe/main/cfe_mem.c
new file mode 100644
index 0000000..1c424e1
--- /dev/null
+++ b/cfe/cfe/main/cfe_mem.c
@@ -0,0 +1,256 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Physical Memory (arena) manager File: cfe_mem.c
+ *
+ * This module describes the physical memory available to the
+ * firmware.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "lib_arena.h"
+
+#include "cfe_error.h"
+
+#include "cfe.h"
+#include "cfe_mem.h"
+
+#include "initdata.h"
+
+#define _NOPROTOS_
+#include "cfe_boot.h"
+#undef _NOPROTOS_
+
+#include "cpu_config.h" /* for definition of CPUCFG_ARENAINIT */
+
+#include "addrspace.h" /* for macros dealing with addresses */
+
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define ARENA_RANGE(bottom,top,type) arena_markrange(&cfe_arena,(uint64_t)(bottom), \
+ (uint64_t)(top)-(uint64_t)bottom+1,(type),NULL)
+
+#define MEG (1024*1024)
+#define KB 1024
+#define PAGESIZE 4096
+#define CFE_BOOTAREA_SIZE (256*KB)
+#define CFE_BOOTAREA_ADDR 0x20000000
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+arena_t cfe_arena;
+extern void _setcontext(int64_t);
+
+unsigned int mem_bootarea_start;
+unsigned int mem_bootarea_size;
+
+extern void CPUCFG_ARENAINIT(void);
+extern void cfe_bootarea_init(void);
+extern void CPUCFG_PAGETBLINIT(uint64_t *ptaddr,unsigned int ptstart);
+
+
+
+/* *********************************************************************
+ * cfe_arena_init()
+ *
+ * Create the initial map of physical memory
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_arena_init(void)
+{
+ uint64_t memlo,memhi;
+
+ /*
+ * This macro expands via cpu_config.h to an appropriate function
+ * name for creating an empty arena appropriately for our CPU
+ */
+
+ CPUCFG_ARENAINIT();
+
+ /*
+ * Round the area used by the firmware to a page boundary and
+ * mark it in use
+ */
+
+ memhi = PHYSADDR((mem_topofmem + 4095) & ~4095);
+ memlo = PHYSADDR(mem_bottomofmem) & ~4095;
+
+ ARENA_RANGE(memlo,memhi-1,MEMTYPE_DRAM_USEDBYFIRMWARE);
+
+ /*
+ * Create the initial page table
+ */
+
+ cfe_bootarea_init();
+
+}
+
+
+/* *********************************************************************
+ * cfe_arena_enum(idx,type,start,size)
+ *
+ * Enumerate available memory. This is called by the user
+ * API dispatcher so that operating systems can determine what
+ * memory regions are available to them.
+ *
+ * Input parameters:
+ * idx - index. Start at zero and increment until an error
+ * is returned.
+ * type,start,size: pointers to variables to receive the
+ * arena entry's information
+ * allrecs - true to retrieve all records, false to retrieve
+ * only available DRAM
+ *
+ * Return value:
+ * 0 if ok
+ * CFE_ERR_NOMORE if idx is beyond the last entry
+ ********************************************************************* */
+
+int cfe_arena_enum(int idx,int *type,uint64_t *start,uint64_t *size,int allrecs)
+{
+ arena_node_t *node;
+ queue_t *qb;
+ arena_t *arena = &cfe_arena;
+
+
+ for (qb = (arena->arena_list.q_next); qb != &(arena->arena_list);
+ qb = qb->q_next) {
+ node = (arena_node_t *) qb;
+
+ if (allrecs || (!allrecs && (node->an_type == MEMTYPE_DRAM_AVAILABLE))) {
+ if (idx == 0) {
+ *type = node->an_type;
+ *start = node->an_address;
+ *size = node->an_length;
+ return 0;
+ }
+ idx--;
+ }
+ }
+
+ return CFE_ERR_NOMORE;
+
+}
+
+/* *********************************************************************
+ * cfe_arena_loadcheck(start,size)
+ *
+ * Determine if the specified memory area is within the available
+ * DRAM. This is used while loading executables to be sure we
+ * don't trash the firmware.
+ *
+ * Input parameters:
+ * start - starting physical address
+ * size - size of requested region
+ *
+ * Return value:
+ * true - ok to copy memory here
+ * false - not ok, memory overlaps firmware
+ ********************************************************************* */
+
+int cfe_arena_loadcheck(uintptr_t start,unsigned int size)
+{
+ arena_node_t *node;
+ queue_t *qb;
+ arena_t *arena = &cfe_arena;
+
+ /*
+ * If the address is in our boot area, it's okay
+ * for it to be a virtual address.
+ */
+
+ if ((start >= BOOT_START_ADDRESS) &&
+ ((start+size) <= (BOOT_START_ADDRESS+BOOT_AREA_SIZE))) {
+ return TRUE;
+ }
+
+ /*
+ * Otherwise, make a physical address.
+ */
+
+ start = PHYSADDR(start);
+
+ /*
+ * Because all of the arena nodes of the same type are
+ * coalesced together, all we need to do is determine if the
+ * requested region is entirely within an arena node,
+ * so there's no need to look for things that span nodes.
+ */
+
+ for (qb = (arena->arena_list.q_next); qb != &(arena->arena_list);
+ qb = qb->q_next) {
+ node = (arena_node_t *) qb;
+
+ /* If the memory is available, the region is OK. */
+
+ if ((start >= node->an_address) &&
+ ((start+size) <= (node->an_address+node->an_length)) &&
+ (node->an_type == MEMTYPE_DRAM_AVAILABLE)) {
+ return TRUE;
+ }
+ }
+
+ /*
+ * Otherwise, it's not. We could go through the arena again and
+ * look for regions of other types that intersect the requested
+ * region, to get a more detailed error, but this'll do.
+ */
+
+ return FALSE;
+
+}
+
diff --git a/cfe/cfe/main/cfe_rawfs.c b/cfe/cfe/main/cfe_rawfs.c
new file mode 100644
index 0000000..4c29349
--- /dev/null
+++ b/cfe/cfe/main/cfe_rawfs.c
@@ -0,0 +1,293 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * "Raw" file system File: cfe_rawfs.c
+ *
+ * This filesystem dispatch is used to read files directly
+ * from a block device. For example, you can 'dd' an elf
+ * file directly onto a disk or flash card and then run
+ * it using this module.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_error.h"
+#include "cfe_fileops.h"
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_console.h"
+
+#include "cfe.h"
+
+/* *********************************************************************
+ * RAW context
+ ********************************************************************* */
+
+/*
+ * File system context - describes overall file system info,
+ * such as the handle to the underlying device.
+ */
+
+typedef struct raw_fsctx_s {
+ int raw_dev;
+ int raw_isconsole;
+ int raw_refcnt;
+} raw_fsctx_t;
+
+/*
+ * File context - describes an open file on the file system.
+ * For raw devices, this is pretty meaningless, but we do
+ * keep track of where we are.
+ */
+
+typedef struct raw_file_s {
+ raw_fsctx_t *raw_fsctx;
+ int raw_fileoffset;
+ int raw_baseoffset; /* starting offset of raw "file" */
+ int raw_length; /* length of file, -1 for whole device */
+} raw_file_t;
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+static int raw_fileop_init(void **fsctx,void *devicename);
+static int raw_fileop_open(void **ref,void *fsctx,char *filename,int mode);
+static int raw_fileop_read(void *ref,uint8_t *buf,int len);
+static int raw_fileop_write(void *ref,uint8_t *buf,int len);
+static int raw_fileop_seek(void *ref,int offset,int how);
+static void raw_fileop_close(void *ref);
+static void raw_fileop_uninit(void *fsctx);
+
+/* *********************************************************************
+ * RAW fileio dispatch table
+ ********************************************************************* */
+
+const fileio_dispatch_t raw_fileops = {
+ "raw",
+ 0,
+ raw_fileop_init,
+ raw_fileop_open,
+ raw_fileop_read,
+ raw_fileop_write,
+ raw_fileop_seek,
+ raw_fileop_close,
+ raw_fileop_uninit
+};
+
+static int raw_fileop_init(void **newfsctx,void *dev)
+{
+ raw_fsctx_t *fsctx;
+ char *devicename = (char *) dev;
+
+ *newfsctx = NULL;
+
+ fsctx = KMALLOC(sizeof(raw_fsctx_t),0);
+ if (!fsctx) {
+ return CFE_ERR_NOMEM;
+ }
+
+ if (strcmp(devicename,console_name) == 0) {
+ fsctx->raw_dev = console_handle;
+ fsctx->raw_isconsole = TRUE;
+ }
+ else {
+ fsctx->raw_dev = cfe_open(devicename);
+ fsctx->raw_isconsole = FALSE;
+ }
+
+ fsctx->raw_refcnt = 0;
+
+ if (fsctx->raw_dev >= 0) {
+ *newfsctx = fsctx;
+ return 0;
+ }
+
+ KFREE(fsctx);
+
+ return CFE_ERR_FILENOTFOUND;
+}
+
+static int raw_fileop_open(void **ref,void *fsctx_arg,char *filename,int mode)
+{
+ raw_fsctx_t *fsctx;
+ raw_file_t *file;
+ char temp[100];
+ char *len;
+
+ if (mode != FILE_MODE_READ) return CFE_ERR_UNSUPPORTED;
+
+ fsctx = (raw_fsctx_t *) fsctx_arg;
+
+ file = KMALLOC(sizeof(raw_file_t),0);
+ if (!file) {
+ return CFE_ERR_NOMEM;
+ }
+
+ file->raw_fileoffset = 0;
+ file->raw_fsctx = fsctx;
+
+ /* Assume the whole device. */
+ file->raw_baseoffset = 0;
+ file->raw_length = -1;
+
+ /*
+ * If a filename was specified, it will be in the form
+ * offset,length - for example, 0x10000,0x200
+ * Parse this into two pieces and set up our internal
+ * file extent information. you can use either decimal
+ * or "0x" notation.
+ */
+ if (filename) {
+ lib_trimleading(filename);
+ strncpy(temp,filename,sizeof(temp));
+ len = strchr(temp,',');
+ if (len) *len++ = '\0';
+ if (temp[0]) {
+ file->raw_baseoffset = lib_atoi(temp);
+ }
+ if (len) {
+ file->raw_length = lib_atoi(len);
+ }
+ }
+
+ fsctx->raw_refcnt++;
+
+ *ref = file;
+ return 0;
+}
+
+static int raw_fileop_read(void *ref,uint8_t *buf,int len)
+{
+ raw_file_t *file = (raw_file_t *) ref;
+ int res;
+
+ /*
+ * Bound the length based on our "file length" if one
+ * was specified.
+ */
+
+ if (file->raw_length >= 0) {
+ if ((file->raw_length - file->raw_fileoffset) < len) {
+ len = file->raw_length - file->raw_fileoffset;
+ }
+ }
+
+ if (len == 0) return 0;
+
+ /*
+ * Read the data, adding in the base address.
+ */
+
+ res = cfe_readblk(file->raw_fsctx->raw_dev,
+ file->raw_baseoffset + file->raw_fileoffset,
+ buf,len);
+
+ if (res > 0) {
+ file->raw_fileoffset += res;
+ }
+
+ return res;
+}
+
+static int raw_fileop_write(void *ref,uint8_t *buf,int len)
+{
+ return CFE_ERR_UNSUPPORTED;
+}
+
+static int raw_fileop_seek(void *ref,int offset,int how)
+{
+ raw_file_t *file = (raw_file_t *) ref;
+
+ switch (how) {
+ case FILE_SEEK_BEGINNING:
+ file->raw_fileoffset = offset;
+ break;
+ case FILE_SEEK_CURRENT:
+ file->raw_fileoffset += offset;
+ if (file->raw_fileoffset < 0) file->raw_fileoffset = 0;
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Make sure we don't attempt to seek past the end of the file.
+ */
+
+ if (file->raw_length >= 0) {
+ if (file->raw_fileoffset > file->raw_length) {
+ file->raw_fileoffset = file->raw_length;
+ }
+ }
+
+ return file->raw_fileoffset;
+}
+
+
+static void raw_fileop_close(void *ref)
+{
+ raw_file_t *file = (raw_file_t *) ref;
+
+ file->raw_fsctx->raw_refcnt--;
+
+ KFREE(file);
+}
+
+static void raw_fileop_uninit(void *fsctx_arg)
+{
+ raw_fsctx_t *fsctx = (raw_fsctx_t *) fsctx_arg;
+
+ if (fsctx->raw_refcnt) {
+ xprintf("raw_fileop_uninit: warning: refcnt not zero\n");
+ }
+
+ if (fsctx->raw_isconsole == FALSE) {
+ cfe_close(fsctx->raw_dev);
+ }
+
+ KFREE(fsctx);
+}
diff --git a/cfe/cfe/main/cfe_savedata.c b/cfe/cfe/main/cfe_savedata.c
new file mode 100644
index 0000000..e1d27c4
--- /dev/null
+++ b/cfe/cfe/main/cfe_savedata.c
@@ -0,0 +1,123 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Data Save routine File: cfe_savedata.c
+ *
+ * This module is used for dumping memory to an output device
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_error.h"
+#include "cfe_devfuncs.h"
+
+#include "cfe.h"
+#include "cfe_fileops.h"
+
+#include "cfe_loader.h"
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+/* *********************************************************************
+ * cfe_savedata(fsname,filename,start,end)
+ *
+ * Write memory contents to the specified device
+ *
+ * Input parameters:
+ * fsname - name of file system
+ * filename - name of file within file system
+ * start - starting address (pointer)
+ * end - ending address (pointer)
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+int cfe_savedata(char *fsname,char *devname,char *filename,uint8_t *start,uint8_t *end)
+{
+ int res;
+ fileio_ctx_t *fsctx;
+ void *ref;
+
+ /*
+ * Create a file system context
+ */
+
+ res = fs_init(fsname,&fsctx,devname);
+ if (res != 0) {
+ return res;
+ }
+
+ /*
+ * Open the device
+ */
+
+ res = fs_open(fsctx,&ref,filename,FILE_MODE_WRITE);
+ if (res != 0) {
+ fs_uninit(fsctx);
+ return res;
+ }
+
+ /*
+ * Write the data
+ */
+
+ res = fs_write(fsctx,ref,start,end-start);
+
+ /*
+ * Close
+ */
+
+ fs_close(fsctx,ref);
+ fs_uninit(fsctx);
+
+ return res;
+
+}
+
diff --git a/cfe/cfe/main/cfe_timer.c b/cfe/cfe/main/cfe_timer.c
new file mode 100644
index 0000000..2b8a0fc
--- /dev/null
+++ b/cfe/cfe/main/cfe_timer.c
@@ -0,0 +1,286 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Timer routines File: cfe_timer.c
+ *
+ * This module contains routines to keep track of the system time,.
+ * Since we don't have any interrupts in the firmware, even the
+ * timer is polled. The timer must be called often enough
+ * to prevent missing the overflow of the CP0 COUNT
+ * register, approximately 2 billion cycles (half the count)
+ *
+ * Be sure to use the POLL() macro each time you enter a loop
+ * where you are waiting for some I/O event to occur or
+ * are waiting for time to elapse.
+ *
+ * It is *not* a time-of-year clock. The timer is only used
+ * for timing I/O events.
+ *
+ * Internally, time is maintained in units of "CLOCKSPERTICK",
+ * which should be about tenths of seconds.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_printf.h"
+
+#include "cfe_timer.h"
+
+#include "cfe.h"
+
+#include "bsp_config.h"
+#include "cpu_config.h"
+
+/* Foxconn add start by Jenny Zhao, 07/02/2008*/
+#include "boardparms.h"
+#include "bcm63xx_util.h"
+#include "tftpd.h"
+/* Foxconn add end by Jenny Zhao, 07/02/2008*/
+
+#ifndef CFG_CPU_SPEED
+#define CFG_CPU_SPEED 500000 /* CPU speed in Hz */
+#endif
+
+#ifndef CPUCFG_CYCLESPERCPUTICK
+#define CPUCFG_CYCLESPERCPUTICK 1 /* CPU clock ticks per CP0 COUNT */
+#endif
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+extern int32_t _getticks(void); /* return value of CP0 COUNT */
+
+/* *********************************************************************
+ * Data
+ ********************************************************************* */
+
+volatile int64_t cfe_ticks; /* current system time */
+
+int cfe_cpu_speed = CFG_CPU_SPEED; /* CPU speed in clocks/second */
+
+static unsigned int cfe_clocks_per_usec;
+static unsigned int cfe_clocks_per_tick;
+
+static int32_t cfe_oldcount; /* For keeping track of ticks */
+static int32_t cfe_remticks;
+static int cfe_timer_initflg = 0;
+
+/*
+ * C0_COUNT clocks per microsecond and per tick. Some CPUs tick CP0
+ * every 'n' cycles, that's what CPUCFG_CYCLESPERCPUTICK is for. */
+#define CFE_CLOCKSPERUSEC (cfe_cpu_speed/1000000/(CPUCFG_CYCLESPERCPUTICK))
+#define CFE_CLOCKSPERTICK (cfe_cpu_speed/(CFE_HZ)/(CPUCFG_CYCLESPERCPUTICK))
+
+/* Foxconn add start by Jenny Zhao, 07/02/2008*/
+extern int ui_docommands(char *str);
+
+extern int g_tftp_upgrade_success;
+extern int nmrp_server_detected;
+
+//extern int g_reboot;
+///* Foxconn add end by Jenny Zhao, 07/02/2008*/
+
+/* *********************************************************************
+ * cfe_timer_task()
+ *
+ * This routine is called as part of normal device polling to
+ * update the system time. We read the CP0 COUNT register,
+ * add the delta into our current time, convert to ticks,
+ * and keep track of the COUNT register overflow
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+static void cfe_timer_task(void *arg)
+{
+ int32_t count;
+ int32_t deltaticks;
+ int32_t clockspertick;
+
+ /* Foxconn add start by Jenny Zhao, 07/02/2008*/
+ static int64_t nmrp_previous_trigger_ticks = 0;
+ static int64_t tftp_previous_trigger_ticks = 0;
+ static int tftp_led_state = 0;
+ /* Foxconn add start by Jenny Zhao, 07/02/2008*/
+
+ clockspertick = CFE_CLOCKSPERTICK;
+
+ count = _getticks();
+
+ if (count >= cfe_oldcount) {
+ deltaticks = (count - cfe_oldcount) / clockspertick;
+ cfe_remticks += (count - cfe_oldcount) % clockspertick;
+ }
+ else {
+ deltaticks = (cfe_oldcount - count) / clockspertick;
+ cfe_remticks += (cfe_oldcount - count) % clockspertick;
+ }
+
+ cfe_ticks += deltaticks + (cfe_remticks / clockspertick);
+ cfe_remticks %= clockspertick;
+ cfe_oldcount = count;
+
+ /* Foxconn add start by Jenny Zhao, 07/02/2008*/
+ if(g_tftp_upgrade_success==1)
+ {
+ if((cfe_ticks - nmrp_previous_trigger_ticks) > 5) //500 ms
+ {
+ nmrp_previous_trigger_ticks = cfe_ticks;
+ nmrp_led_toggle();
+ }
+ }
+
+ /* Blink Power LED in tftpd mode */
+ if ( (get_tftpd_state() != TFTPD_STATE_OFF) && (nmrp_server_detected==0) )
+ {
+ if(tftp_led_state == 0) //led is off
+ {
+ if((cfe_ticks - tftp_previous_trigger_ticks) > 7) //700ms, spec. is 750ms
+ {
+ tftp_led_state = 1;
+ power_led_toggle(tftp_led_state);
+ tftp_previous_trigger_ticks = cfe_ticks;
+ }
+ }
+ else // led is currently on
+ {
+ if((cfe_ticks - tftp_previous_trigger_ticks) > 3) //300ms, spec. is 250ms
+ {
+ tftp_led_state = 0;
+ power_led_toggle(tftp_led_state);
+ tftp_previous_trigger_ticks = cfe_ticks;
+ }
+ }
+ }
+ /* Foxconn add end by Jenny Zhao, 07/02/2008*/
+}
+
+
+/* *********************************************************************
+ * cfe_timer_init()
+ *
+ * Initialize the timer module.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_timer_init(void)
+{
+ cfe_clocks_per_tick = CFE_CLOCKSPERTICK;
+ cfe_clocks_per_usec = CFE_CLOCKSPERUSEC;
+ if (cfe_clocks_per_usec == 0)
+ cfe_clocks_per_usec = 1; /* for the simulator */
+
+ cfe_oldcount = _getticks(); /* get current COUNT register */
+ cfe_ticks = 0;
+
+ if (!cfe_timer_initflg) {
+ cfe_bg_add(cfe_timer_task,NULL); /* add task for background polling */
+ cfe_timer_initflg = 1;
+ }
+}
+
+
+/* *********************************************************************
+ * cfe_sleep(ticks)
+ *
+ * Sleep for 'ticks' ticks. Background tasks are processed while
+ * we wait.
+ *
+ * Input parameters:
+ * ticks - number of ticks to sleep (note: *not* clocks!)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_sleep(int ticks)
+{
+ int64_t timer;
+
+ TIMER_SET(timer,ticks);
+ while (!TIMER_EXPIRED(timer)) {
+ POLL();
+ }
+}
+
+
+
+/* *********************************************************************
+ * cfe_usleep(usec)
+ *
+ * Sleep for approximately the specified number of microseconds.
+ *
+ * Input parameters:
+ * usec - number of microseconds to wait
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void cfe_usleep(int usec)
+{
+ uint32_t newcount;
+ uint32_t now;
+
+ /* XXX fix the wrap problem */
+
+ now = _getticks();
+ newcount = now + usec*cfe_clocks_per_usec;
+
+ if (newcount < now) /* wait for wraparound */
+ while (_getticks() > now)
+ ;
+
+
+ while (_getticks() < newcount)
+ ;
+}
diff --git a/cfe/cfe/main/cfe_version.mk b/cfe/cfe/main/cfe_version.mk
new file mode 100755
index 0000000..653cbf9
--- /dev/null
+++ b/cfe/cfe/main/cfe_version.mk
@@ -0,0 +1,12 @@
+
+#
+# CFE's version number
+# Warning: Don't put spaces on either side of the equal signs
+# Put just the version number in here. This file is sourced
+# like a shell script in some cases!
+#
+
+CFE_VER_MAJ=1
+CFE_VER_MIN=0
+CFE_VER_ECO=37
+
diff --git a/cfe/cfe/main/cfe_xreq.c b/cfe/cfe/main/cfe_xreq.c
new file mode 100644
index 0000000..d12b1f2
--- /dev/null
+++ b/cfe/cfe/main/cfe_xreq.c
@@ -0,0 +1,346 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * IOCB dispatcher File: cfe_xreq.c
+ *
+ * This routine is the main API dispatch for CFE. User API
+ * calls, via the ROM entry point, get dispatched to routines
+ * in this module.
+ *
+ * This module looks similar to cfe_iocb_dispatch - it is different
+ * in that the data structure used, cfe_xiocb_t, uses fixed
+ * size field members (specifically, all 64-bits) no matter how
+ * the firmware is compiled. This ensures a consistent API
+ * interface on any implementation. When you call CFE
+ * from another program, the entry vector comes here first.
+ *
+ * Should the normal cfe_iocb interface change, this one should
+ * be kept the same for backward compatibility reasons.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "bsp_config.h"
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "cfe_iocb.h"
+#include "cfe_xiocb.h"
+#if CFG_VENDOR_EXTENSIONS
+#include "cfe_vendor_iocb.h"
+#include "cfe_vendor_xiocb.h"
+#endif
+#include "cfe_error.h"
+#include "cfe_device.h"
+#include "cfe_timer.h"
+#include "cfe_mem.h"
+#include "env_subr.h"
+#include "cfe.h"
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+/* enum values for various plist types */
+
+#define PLBUF 1 /* iocb_buffer_t */
+#define PLCPU 2 /* iocb_cpuctl_t */
+#define PLMEM 3 /* iocb_meminfo_t */
+#define PLENV 4 /* iocb_envbuf_t */
+#define PLINP 5 /* iocb_inpstat_t */
+#define PLTIM 6 /* iocb_time_t */
+#define PLINF 7 /* iocb_fwinfo_t */
+#define PLEXIT 8 /* iocb_exitstat_t */
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+struct cfe_xcmd_dispatch_s {
+ int xplistsize;
+ int iplistsize;
+ int plisttype;
+};
+
+
+/* *********************************************************************
+ * Command conversion table
+ * This table contains useful information for converting
+ * iocbs to xiocbs.
+ ********************************************************************* */
+
+const static struct cfe_xcmd_dispatch_s cfe_xcmd_dispatch_table[CFE_CMD_MAX] = {
+ {sizeof(xiocb_fwinfo_t), sizeof(iocb_fwinfo_t), PLINF}, /* 0 : CFE_CMD_FW_GETINFO */
+ {sizeof(xiocb_exitstat_t),sizeof(iocb_exitstat_t),PLEXIT}, /* 1 : CFE_CMD_FW_RESTART */
+ {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 2 : CFE_CMD_FW_BOOT */
+ {sizeof(xiocb_cpuctl_t), sizeof(iocb_cpuctl_t), PLCPU}, /* 3 : CFE_CMD_FW_CPUCTL */
+ {sizeof(xiocb_time_t), sizeof(iocb_time_t), PLTIM}, /* 4 : CFE_CMD_FW_GETTIME */
+ {sizeof(xiocb_meminfo_t),sizeof(iocb_meminfo_t),PLMEM}, /* 5 : CFE_CMD_FW_MEMENUM */
+ {0, 0, 0}, /* 6 : CFE_CMD_FW_FLUSHCACHE */
+ {-1, 0, 0}, /* 7 : */
+ {-1, 0, 0}, /* 8 : */
+ {0, 0, 0}, /* 9 : CFE_CMD_DEV_GETHANDLE */
+ {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV}, /* 10 : CFE_CMD_DEV_ENUM */
+ {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 11 : CFE_CMD_DEV_OPEN_*/
+ {sizeof(xiocb_inpstat_t),sizeof(iocb_inpstat_t),PLINP}, /* 12 : CFE_CMD_DEV_INPSTAT */
+ {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 13 : CFE_CMD_DEV_READ */
+ {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 14 : CFE_CMD_DEV_WRITE */
+ {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 15 : CFE_CMD_DEV_IOCTL */
+ {0, 0, 0}, /* 16 : CFE_CMD_DEV_CLOSE */
+ {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 17 : CFE_CMD_DEV_GETINFO */
+ {-1, 0, 0}, /* 18 : */
+ {-1, 0, 0}, /* 19 : */
+ {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV}, /* 20 : CFE_CMD_ENV_ENUM */
+ {-1, 0, 0}, /* 21 : */
+ {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV}, /* 22 : CFE_CMD_ENV_GET */
+ {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV}, /* 23 : CFE_CMD_ENV_SET */
+ {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV}, /* 24 : CFE_CMD_ENV_DEL */
+ {-1, 0, 0}, /* 25 : */
+ {-1, 0, 0}, /* 26 : */
+ {-1, 0, 0}, /* 27 : */
+ {-1, 0, 0}, /* 28 : */
+ {-1, 0, 0}, /* 29 : */
+ {-1, 0, 0}, /* 30 : */
+ {-1, 0, 0} /* 31 : */
+};
+
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+extern int cfe_iocb_dispatch(cfe_iocb_t *iocb);
+cfe_int_t cfe_doxreq(cfe_xiocb_t *xiocb);
+#if CFG_VENDOR_EXTENSIONS
+extern cfe_int_t cfe_vendor_doxreq(cfe_vendor_xiocb_t *xiocb);
+#endif
+
+/* *********************************************************************
+ * cfe_doxreq(xiocb)
+ *
+ * Process an xiocb request. This routine converts an xiocb
+ * into an iocb, calls the IOCB dispatcher, converts the results
+ * back into the xiocb, and returns.
+ *
+ * Input parameters:
+ * xiocb - pointer to user xiocb
+ *
+ * Return value:
+ * command status, <0 if error occured
+ ********************************************************************* */
+
+cfe_int_t cfe_doxreq(cfe_xiocb_t *xiocb)
+{
+ const struct cfe_xcmd_dispatch_s *disp;
+ cfe_iocb_t iiocb;
+ cfe_int_t res;
+
+ /*
+ * Call out to customer-specific IOCBs. Customers may choose
+ * to implement their own XIOCBs directly, or go through their own
+ * translation layer (xiocb->iocb like CFE does) to insulate
+ * themselves from IOCB changes in the future.
+ */
+ if (xiocb->xiocb_fcode >= CFE_CMD_VENDOR_USE) {
+#if CFG_VENDOR_EXTENSIONS
+ return cfe_vendor_doxreq((cfe_vendor_xiocb_t *)xiocb);
+#else
+ return CFE_ERR_INV_COMMAND;
+#endif
+ }
+
+ /*
+ * Check for commands codes out of range
+ */
+
+ if ((xiocb->xiocb_fcode < 0) || (xiocb->xiocb_fcode >= CFE_CMD_MAX)) {
+ xiocb->xiocb_status = CFE_ERR_INV_COMMAND;
+ return xiocb->xiocb_status;
+ }
+
+ /*
+ * Check for command codes in range but invalid
+ */
+
+ disp = &cfe_xcmd_dispatch_table[xiocb->xiocb_fcode];
+
+ if (disp->xplistsize < 0) {
+ xiocb->xiocb_status = CFE_ERR_INV_COMMAND;
+ return xiocb->xiocb_status;
+ }
+
+ /*
+ * Check for invalid parameter list size
+ */
+
+ if (disp->xplistsize != xiocb->xiocb_psize) {
+ xiocb->xiocb_status = CFE_ERR_INV_PARAM;
+ return xiocb->xiocb_status;
+ }
+
+ /*
+ * Okay, copy parameters into the internal IOCB.
+ * First, the fixed header.
+ */
+
+ iiocb.iocb_fcode = (unsigned int) xiocb->xiocb_fcode;
+ iiocb.iocb_status = (int) xiocb->xiocb_status;
+ iiocb.iocb_handle = (int) xiocb->xiocb_handle;
+ iiocb.iocb_flags = (unsigned int) xiocb->xiocb_flags;
+ iiocb.iocb_psize = (unsigned int) disp->iplistsize;
+
+ /*
+ * Now the parameter list
+ */
+
+ switch (disp->plisttype) {
+ case PLBUF:
+ iiocb.plist.iocb_buffer.buf_offset = (cfe_offset_t) xiocb->plist.xiocb_buffer.buf_offset;
+ iiocb.plist.iocb_buffer.buf_ptr = (unsigned char *) (uintptr_t) xiocb->plist.xiocb_buffer.buf_ptr;
+ iiocb.plist.iocb_buffer.buf_length = (unsigned int) xiocb->plist.xiocb_buffer.buf_length;
+ iiocb.plist.iocb_buffer.buf_retlen = (unsigned int) xiocb->plist.xiocb_buffer.buf_retlen;
+ iiocb.plist.iocb_buffer.buf_ioctlcmd = (unsigned int) xiocb->plist.xiocb_buffer.buf_ioctlcmd;
+ break;
+ case PLCPU:
+ iiocb.plist.iocb_cpuctl.cpu_number = (unsigned int) xiocb->plist.xiocb_cpuctl.cpu_number;
+ iiocb.plist.iocb_cpuctl.cpu_command = (unsigned int) xiocb->plist.xiocb_cpuctl.cpu_command;
+ iiocb.plist.iocb_cpuctl.start_addr = (unsigned long) xiocb->plist.xiocb_cpuctl.start_addr;
+ iiocb.plist.iocb_cpuctl.gp_val = (unsigned long) xiocb->plist.xiocb_cpuctl.gp_val;
+ iiocb.plist.iocb_cpuctl.sp_val = (unsigned long) xiocb->plist.xiocb_cpuctl.sp_val;
+ iiocb.plist.iocb_cpuctl.a1_val = (unsigned long) xiocb->plist.xiocb_cpuctl.a1_val;
+ break;
+ case PLMEM:
+ iiocb.plist.iocb_meminfo.mi_idx = (int) xiocb->plist.xiocb_meminfo.mi_idx;
+ iiocb.plist.iocb_meminfo.mi_type = (int) xiocb->plist.xiocb_meminfo.mi_type;
+ iiocb.plist.iocb_meminfo.mi_addr = (unsigned long long) xiocb->plist.xiocb_meminfo.mi_addr;
+ iiocb.plist.iocb_meminfo.mi_size = (unsigned long long) xiocb->plist.xiocb_meminfo.mi_size;
+ break;
+ case PLENV:
+ iiocb.plist.iocb_envbuf.enum_idx = (int) xiocb->plist.xiocb_envbuf.enum_idx;
+ iiocb.plist.iocb_envbuf.name_ptr = (unsigned char *) (uintptr_t) xiocb->plist.xiocb_envbuf.name_ptr;
+ iiocb.plist.iocb_envbuf.name_length = (int) xiocb->plist.xiocb_envbuf.name_length;
+ iiocb.plist.iocb_envbuf.val_ptr = (unsigned char *) (uintptr_t) xiocb->plist.xiocb_envbuf.val_ptr;
+ iiocb.plist.iocb_envbuf.val_length = (int) xiocb->plist.xiocb_envbuf.val_length;
+ break;
+ case PLINP:
+ iiocb.plist.iocb_inpstat.inp_status = (int) xiocb->plist.xiocb_inpstat.inp_status;
+ break;
+ case PLTIM:
+ iiocb.plist.iocb_time.ticks = (long long) xiocb->plist.xiocb_time.ticks;
+ break;
+ case PLINF:
+ break;
+ case PLEXIT:
+ iiocb.plist.iocb_exitstat.status = (long long) xiocb->plist.xiocb_exitstat.status;
+ break;
+ }
+
+ /*
+ * Do the internal function dispatch
+ */
+
+ res = (cfe_int_t) cfe_iocb_dispatch(&iiocb);
+
+ /*
+ * Now convert the parameter list members back
+ */
+
+ switch (disp->plisttype) {
+ case PLBUF:
+ xiocb->plist.xiocb_buffer.buf_offset = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_offset;
+ xiocb->plist.xiocb_buffer.buf_ptr = (cfe_xptr_t) (uintptr_t) iiocb.plist.iocb_buffer.buf_ptr;
+ xiocb->plist.xiocb_buffer.buf_length = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_length;
+ xiocb->plist.xiocb_buffer.buf_retlen = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_retlen;
+ xiocb->plist.xiocb_buffer.buf_ioctlcmd = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_ioctlcmd;
+ break;
+ case PLCPU:
+ xiocb->plist.xiocb_cpuctl.cpu_number = (cfe_uint_t) iiocb.plist.iocb_cpuctl.cpu_number;
+ xiocb->plist.xiocb_cpuctl.cpu_command = (cfe_uint_t) iiocb.plist.iocb_cpuctl.cpu_command;
+ xiocb->plist.xiocb_cpuctl.start_addr = (cfe_uint_t) iiocb.plist.iocb_cpuctl.start_addr;
+ break;
+ case PLMEM:
+ xiocb->plist.xiocb_meminfo.mi_idx = (cfe_int_t) iiocb.plist.iocb_meminfo.mi_idx;
+ xiocb->plist.xiocb_meminfo.mi_type = (cfe_int_t) iiocb.plist.iocb_meminfo.mi_type;
+ xiocb->plist.xiocb_meminfo.mi_addr = (cfe_int64_t) iiocb.plist.iocb_meminfo.mi_addr;
+ xiocb->plist.xiocb_meminfo.mi_size = (cfe_int64_t) iiocb.plist.iocb_meminfo.mi_size;
+ break;
+ case PLENV:
+ xiocb->plist.xiocb_envbuf.enum_idx = (cfe_int_t) iiocb.plist.iocb_envbuf.enum_idx;
+ xiocb->plist.xiocb_envbuf.name_ptr = (cfe_xptr_t) (uintptr_t) iiocb.plist.iocb_envbuf.name_ptr;
+ xiocb->plist.xiocb_envbuf.name_length = (cfe_int_t) iiocb.plist.iocb_envbuf.name_length;
+ xiocb->plist.xiocb_envbuf.val_ptr = (cfe_xptr_t) (uintptr_t) iiocb.plist.iocb_envbuf.val_ptr;
+ xiocb->plist.xiocb_envbuf.val_length = (cfe_int_t) iiocb.plist.iocb_envbuf.val_length;
+ break;
+ case PLINP:
+ xiocb->plist.xiocb_inpstat.inp_status = (cfe_int_t) iiocb.plist.iocb_inpstat.inp_status;
+ break;
+ case PLTIM:
+ xiocb->plist.xiocb_time.ticks = (cfe_int_t) iiocb.plist.iocb_time.ticks;
+ break;
+ case PLINF:
+ xiocb->plist.xiocb_fwinfo.fwi_version = iiocb.plist.iocb_fwinfo.fwi_version;
+ xiocb->plist.xiocb_fwinfo.fwi_totalmem = iiocb.plist.iocb_fwinfo.fwi_totalmem;
+ xiocb->plist.xiocb_fwinfo.fwi_flags = iiocb.plist.iocb_fwinfo.fwi_flags;
+ xiocb->plist.xiocb_fwinfo.fwi_boardid = iiocb.plist.iocb_fwinfo.fwi_boardid;
+ xiocb->plist.xiocb_fwinfo.fwi_bootarea_va = iiocb.plist.iocb_fwinfo.fwi_bootarea_va;
+ xiocb->plist.xiocb_fwinfo.fwi_bootarea_pa = iiocb.plist.iocb_fwinfo.fwi_bootarea_pa;
+ xiocb->plist.xiocb_fwinfo.fwi_bootarea_size = iiocb.plist.iocb_fwinfo.fwi_bootarea_size;
+ xiocb->plist.xiocb_fwinfo.fwi_reserved1 = iiocb.plist.iocb_fwinfo.fwi_reserved1;
+ xiocb->plist.xiocb_fwinfo.fwi_reserved2 = iiocb.plist.iocb_fwinfo.fwi_reserved2;
+ xiocb->plist.xiocb_fwinfo.fwi_reserved3 = iiocb.plist.iocb_fwinfo.fwi_reserved3;
+ break;
+ case PLEXIT:
+ xiocb->plist.xiocb_exitstat.status = (cfe_int_t) iiocb.plist.iocb_exitstat.status;
+ break;
+ }
+
+ /*
+ * And the fixed header
+ */
+
+ xiocb->xiocb_status = (cfe_int_t) iiocb.iocb_status;
+ xiocb->xiocb_handle = (cfe_int_t) iiocb.iocb_handle;
+ xiocb->xiocb_flags = (cfe_uint_t) iiocb.iocb_flags;
+
+ return xiocb->xiocb_status;
+}
diff --git a/cfe/cfe/main/cfe_zlibfs.c b/cfe/cfe/main/cfe_zlibfs.c
new file mode 100644
index 0000000..7ad0847
--- /dev/null
+++ b/cfe/cfe/main/cfe_zlibfs.c
@@ -0,0 +1,453 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * "Compressed" file system File: cfe_zlibfs.c
+ *
+ * This is more of a filesystem "hook" than an actual file system.
+ * You can stick it on the front of the chain of file systems
+ * that CFE calls and it will route data read from the
+ * underlying filesystem through ZLIB before passing it up to the
+ * user.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#if CFG_ZLIB
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_error.h"
+#include "cfe_fileops.h"
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_console.h"
+
+#include "cfe.h"
+
+#include "zlib.h"
+
+/* *********************************************************************
+ * ZLIBFS context
+ ********************************************************************* */
+
+/*
+ * File system context - describes overall file system info,
+ * such as the handle to the underlying device.
+ */
+
+typedef struct zlibfs_fsctx_s {
+ void *zlibfsctx_subfsctx;
+ const fileio_dispatch_t *zlibfsctx_subops;
+ int zlibfsctx_refcnt;
+} zlibfs_fsctx_t;
+
+/*
+ * File context - describes an open file on the file system.
+ * For raw devices, this is pretty meaningless, but we do
+ * keep track of where we are.
+ */
+
+#define ZLIBFS_BUFSIZE 1024
+typedef struct zlibfs_file_s {
+ zlibfs_fsctx_t *zlibfs_fsctx;
+ int zlibfs_fileoffset;
+ void *zlibfs_subfile;
+ z_stream zlibfs_stream;
+ uint8_t *zlibfs_inbuf;
+ uint8_t *zlibfs_outbuf;
+ int zlibfs_outlen;
+ uint8_t *zlibfs_outptr;
+ int zlibfs_eofseen;
+} zlibfs_file_t;
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+static int zlibfs_fileop_init(void **fsctx,void *ctx);
+static int zlibfs_fileop_open(void **ref,void *fsctx,char *filename,int mode);
+static int zlibfs_fileop_read(void *ref,uint8_t *buf,int len);
+static int zlibfs_fileop_write(void *ref,uint8_t *buf,int len);
+static int zlibfs_fileop_seek(void *ref,int offset,int how);
+static void zlibfs_fileop_close(void *ref);
+static void zlibfs_fileop_uninit(void *fsctx);
+
+voidpf zcalloc(voidpf opaque,unsigned items, unsigned size);
+void zcfree(voidpf opaque,voidpf ptr);
+
+/* *********************************************************************
+ * ZLIB fileio dispatch table
+ ********************************************************************* */
+
+
+static uint8_t gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
+
+
+/* gzip flag byte */
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define RESERVED 0xE0 /* bits 5..7: reserved */
+
+const fileio_dispatch_t zlibfs_fileops = {
+ "z",
+ 0,
+ zlibfs_fileop_init,
+ zlibfs_fileop_open,
+ zlibfs_fileop_read,
+ zlibfs_fileop_write,
+ zlibfs_fileop_seek,
+ zlibfs_fileop_close,
+ zlibfs_fileop_uninit
+};
+
+/*
+ * Utility functions needed by the ZLIB routines
+ */
+voidpf zcalloc(voidpf opaque,unsigned items, unsigned size)
+{
+ void *ptr;
+
+ ptr = KMALLOC(items*size,0);
+ if (ptr) lib_memset(ptr,0,items*size);
+ return ptr;
+}
+
+void zcfree(voidpf opaque,voidpf ptr)
+{
+ KFREE(ptr);
+}
+
+
+static int zlibfs_fileop_init(void **newfsctx,void *curfsvoid)
+{
+ zlibfs_fsctx_t *fsctx;
+ fileio_ctx_t *curfsctx = (fileio_ctx_t *) curfsvoid;
+
+ *newfsctx = NULL;
+
+ fsctx = KMALLOC(sizeof(zlibfs_fsctx_t),0);
+ if (!fsctx) {
+ return CFE_ERR_NOMEM;
+ }
+
+ fsctx->zlibfsctx_refcnt = 0;
+ fsctx->zlibfsctx_subops = curfsctx->ops;
+ fsctx->zlibfsctx_subfsctx = curfsctx->fsctx;
+
+ *newfsctx = fsctx;
+
+ return 0;
+}
+
+
+static int get_byte(zlibfs_file_t *file,uint8_t *ch)
+{
+ int res;
+
+ res = BDREAD(file->zlibfs_fsctx->zlibfsctx_subops,
+ file->zlibfs_subfile,
+ ch,
+ 1);
+
+ return res;
+}
+
+
+static int check_header(zlibfs_file_t *file)
+{
+ int method; /* method byte */
+ int flags; /* flags byte */
+ uInt len;
+ uint8_t c;
+ int res;
+
+ /* Check the gzip magic header */
+ for (len = 0; len < 2; len++) {
+ res = get_byte(file,&c);
+ if (c != gz_magic[len]) {
+ return -1;
+ }
+ }
+
+ get_byte(file,&c); method = (int) c;
+ get_byte(file,&c); flags = (int) c;
+
+ if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
+ return -1;
+ }
+
+ /* Discard time, xflags and OS code: */
+ for (len = 0; len < 6; len++) (void)get_byte(file,&c);
+
+ if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
+ get_byte(file,&c);
+ len = (uInt) c;
+ get_byte(file,&c);
+ len += ((uInt)c)<<8;
+ /* len is garbage if EOF but the loop below will quit anyway */
+ while ((len-- != 0) && (get_byte(file,&c) == 1)) ;
+ }
+ if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
+ while ((get_byte(file,&c) == 1) && (c != 0)) ;
+ }
+ if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
+ while ((get_byte(file,&c) == 1) && (c != 0)) ;
+ }
+ if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
+ for (len = 0; len < 2; len++) (void)get_byte(file,&c);
+ }
+
+ return 0;
+}
+
+static int zlibfs_fileop_open(void **ref,void *fsctx_arg,char *filename,int mode)
+{
+ zlibfs_fsctx_t *fsctx;
+ zlibfs_file_t *file;
+ int err;
+
+ if (mode != FILE_MODE_READ) return CFE_ERR_UNSUPPORTED;
+
+ fsctx = (zlibfs_fsctx_t *) fsctx_arg;
+
+ file = KMALLOC(sizeof(zlibfs_file_t),0);
+ if (!file) {
+ return CFE_ERR_NOMEM;
+ }
+
+ file->zlibfs_fileoffset = 0;
+ file->zlibfs_fsctx = fsctx;
+ file->zlibfs_inbuf = NULL;
+ file->zlibfs_outbuf = NULL;
+ file->zlibfs_eofseen = 0;
+
+ err = BDOPEN(fsctx->zlibfsctx_subops,&(file->zlibfs_subfile),
+ fsctx->zlibfsctx_subfsctx,filename);
+
+ if (err != 0) {
+ goto error2;
+ return err;
+ }
+
+ /* Open the zstream */
+
+ file->zlibfs_inbuf = KMALLOC(ZLIBFS_BUFSIZE,0);
+ file->zlibfs_outbuf = KMALLOC(ZLIBFS_BUFSIZE,0);
+
+ if (!file->zlibfs_inbuf || !file->zlibfs_outbuf) {
+ err = CFE_ERR_NOMEM;
+ goto error;
+ }
+
+ file->zlibfs_stream.next_in = NULL;
+ file->zlibfs_stream.avail_in = 0;
+ file->zlibfs_stream.next_out = file->zlibfs_outbuf;
+ file->zlibfs_stream.avail_out = ZLIBFS_BUFSIZE;
+ file->zlibfs_stream.zalloc = (alloc_func)0;
+ file->zlibfs_stream.zfree = (free_func)0;
+
+ file->zlibfs_outlen = 0;
+ file->zlibfs_outptr = file->zlibfs_outbuf;
+
+ err = inflateInit2(&(file->zlibfs_stream),-15);
+ if (err != Z_OK) {
+ err = CFE_ERR;
+ goto error;
+ }
+
+ check_header(file);
+
+ fsctx->zlibfsctx_refcnt++;
+
+ *ref = file;
+ return 0;
+
+error:
+ BDCLOSE(file->zlibfs_fsctx->zlibfsctx_subops,file->zlibfs_subfile);
+error2:
+ if (file->zlibfs_inbuf) KFREE(file->zlibfs_inbuf);
+ if (file->zlibfs_outbuf) KFREE(file->zlibfs_outbuf);
+ KFREE(file);
+ return err;
+}
+
+static int zlibfs_fileop_read(void *ref,uint8_t *buf,int len)
+{
+ zlibfs_file_t *file = (zlibfs_file_t *) ref;
+ int res = 0;
+ int err;
+ int amtcopy;
+ int ttlcopy = 0;
+
+ if (len == 0) return 0;
+
+ while (len) {
+
+ /* Figure the amount to copy. This is the min of what we
+ have left to do and what is available. */
+ amtcopy = len;
+ if (amtcopy > file->zlibfs_outlen) {
+ amtcopy = file->zlibfs_outlen;
+ }
+
+ /* Copy the data. */
+
+ if (buf) {
+ memcpy(buf,file->zlibfs_outptr,amtcopy);
+ buf += amtcopy;
+ }
+
+ /* Update the pointers. */
+ file->zlibfs_outptr += amtcopy;
+ file->zlibfs_outlen -= amtcopy;
+ len -= amtcopy;
+ ttlcopy += amtcopy;
+
+ /* If we've eaten all of the output, reset and call inflate
+ again. */
+
+ if (file->zlibfs_outlen == 0) {
+ /* If no input data to decompress, get some more if we can. */
+ if (file->zlibfs_eofseen) break;
+ if (file->zlibfs_stream.avail_in == 0) {
+ res = BDREAD(file->zlibfs_fsctx->zlibfsctx_subops,
+ file->zlibfs_subfile,
+ file->zlibfs_inbuf,
+ ZLIBFS_BUFSIZE);
+ /* If at EOF or error, get out. */
+ if (res <= 0) break;
+ file->zlibfs_stream.next_in = file->zlibfs_inbuf;
+ file->zlibfs_stream.avail_in = res;
+ }
+
+ /* inflate the input data. */
+ file->zlibfs_stream.next_out = file->zlibfs_outbuf;
+ file->zlibfs_stream.avail_out = ZLIBFS_BUFSIZE;
+ file->zlibfs_outptr = file->zlibfs_outbuf;
+ err = inflate(&(file->zlibfs_stream),Z_SYNC_FLUSH);
+ if (err == Z_STREAM_END) {
+ /* We can get a partial buffer fill here. */
+ file->zlibfs_eofseen = 1;
+ }
+ else if (err != Z_OK) {
+ res = CFE_ERR;
+ break;
+ }
+ file->zlibfs_outlen = file->zlibfs_stream.next_out -
+ file->zlibfs_outptr;
+ }
+
+ }
+
+ file->zlibfs_fileoffset += ttlcopy;
+
+ return (res < 0) ? res : ttlcopy;
+}
+
+static int zlibfs_fileop_write(void *ref,uint8_t *buf,int len)
+{
+ return CFE_ERR_UNSUPPORTED;
+}
+
+static int zlibfs_fileop_seek(void *ref,int offset,int how)
+{
+ zlibfs_file_t *file = (zlibfs_file_t *) ref;
+ int res;
+ int delta;
+
+ switch (how) {
+ case FILE_SEEK_BEGINNING:
+ delta = offset - file->zlibfs_fileoffset;
+ break;
+ case FILE_SEEK_CURRENT:
+ delta = offset;
+ break;
+ default:
+ return CFE_ERR_UNSUPPORTED;
+ break;
+ }
+
+ /* backward seeking not allowed on compressed streams */
+ if (delta < 0) {
+ return CFE_ERR_UNSUPPORTED;
+ }
+
+ res = zlibfs_fileop_read(ref,NULL,delta);
+
+ if (res < 0) return res;
+
+ return file->zlibfs_fileoffset;
+}
+
+
+static void zlibfs_fileop_close(void *ref)
+{
+ zlibfs_file_t *file = (zlibfs_file_t *) ref;
+
+ file->zlibfs_fsctx->zlibfsctx_refcnt--;
+
+ inflateEnd(&(file->zlibfs_stream));
+
+ BDCLOSE(file->zlibfs_fsctx->zlibfsctx_subops,file->zlibfs_subfile);
+
+ KFREE(file);
+}
+
+static void zlibfs_fileop_uninit(void *fsctx_arg)
+{
+ zlibfs_fsctx_t *fsctx = (zlibfs_fsctx_t *) fsctx_arg;
+
+ if (fsctx->zlibfsctx_refcnt) {
+ xprintf("zlibfs_fileop_uninit: warning: refcnt not zero\n");
+ }
+
+ BDUNINIT(fsctx->zlibfsctx_subops,fsctx->zlibfsctx_subfsctx);
+
+ KFREE(fsctx);
+}
+
+
+#endif
diff --git a/cfe/cfe/main/env_subr.c b/cfe/cfe/main/env_subr.c
new file mode 100644
index 0000000..5f12359
--- /dev/null
+++ b/cfe/cfe/main/env_subr.c
@@ -0,0 +1,474 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Environment variable subroutines File: env_subr.c
+ *
+ * This module contains routines to muck with environment variables
+ * (manage the list, read/write to nvram, etc.)
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "env_subr.h"
+#include "nvram_subr.h"
+
+#include "cfe_error.h"
+#include "cfe.h"
+
+/* *********************************************************************
+ * Types
+ ********************************************************************* */
+
+typedef struct cfe_envvar_s {
+ queue_t qb;
+ int flags;
+ char *name;
+ char *value;
+ /* name and value go here */
+} cfe_envvar_t;
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+queue_t env_envvars = {&env_envvars,&env_envvars};
+extern unsigned int cfe_startflags;
+
+/* *********************************************************************
+ * env_findenv(name)
+ *
+ * Locate an environment variable in the in-memory list
+ *
+ * Input parameters:
+ * name - name of env var to find
+ *
+ * Return value:
+ * cfe_envvar_t pointer, or NULL if not found
+ ********************************************************************* */
+
+static cfe_envvar_t *env_findenv(const char *name)
+{
+ queue_t *qb;
+ cfe_envvar_t *env;
+
+ for (qb = env_envvars.q_next; qb != &env_envvars; qb = qb->q_next) {
+ env = (cfe_envvar_t *) qb;
+ if (strcmp(env->name,name) == 0) break;
+ }
+
+ if (qb == &env_envvars) return NULL;
+
+ return (cfe_envvar_t *) qb;
+
+}
+
+/* *********************************************************************
+ * env_enum(idx,name,namelen,val,vallen)
+ *
+ * Enumerate environment variables. This routine locates
+ * the nth environment variable and copies its name and value
+ * to user buffers.
+ *
+ * The namelen and vallen variables must be preinitialized to
+ * the maximum size of the output buffer.
+ *
+ * Input parameters:
+ * idx - variable index to find (starting with zero)
+ * name,namelen - name buffer and length
+ * val,vallen - value buffer and length
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int env_enum(int idx,char *name,int *namelen,char *val,int *vallen)
+{
+ queue_t *qb;
+ cfe_envvar_t *env;
+
+ for (qb = env_envvars.q_next; qb != &env_envvars; qb = qb->q_next) {
+ if (idx == 0) break;
+ idx--;
+ }
+
+ if (qb == &env_envvars) return CFE_ERR_ENVNOTFOUND;
+ env = (cfe_envvar_t *) qb;
+
+ *namelen = xstrncpy(name,env->name,*namelen);
+ *vallen = xstrncpy(val,env->value,*vallen);
+
+ return 0;
+
+}
+
+/* *********************************************************************
+ * env_envtype(name)
+ *
+ * Return the type of the environment variable
+ *
+ * Input parameters:
+ * name - name of environment variable
+ *
+ * Return value:
+ * flags, or <0 if error occured
+ ********************************************************************* */
+int env_envtype(const char *name)
+{
+ cfe_envvar_t *env;
+
+ env = env_findenv(name);
+
+ if (env) {
+ return env->flags;
+ }
+
+ return CFE_ERR_ENVNOTFOUND;
+}
+
+
+
+/* *********************************************************************
+ * env_delenv(name)
+ *
+ * Delete an environment variable
+ *
+ * Input parameters:
+ * name - environment variable to delete
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int env_delenv(const char *name)
+{
+ cfe_envvar_t *env;
+
+ env = env_findenv(name);
+
+ if (!env) return 0;
+
+ if (!(env->flags & ENV_FLG_READONLY)) {
+ q_dequeue((queue_t *) env);
+ KFREE(env);
+ return 0;
+ }
+
+ return CFE_ERR_ENVNOTFOUND;
+}
+
+/* *********************************************************************
+ * env_getenv(name)
+ *
+ * Retrieve the value of an environment variable
+ *
+ * Input parameters:
+ * name - name of environment variable to find
+ *
+ * Return value:
+ * value, or NULL if variable is not found
+ ********************************************************************* */
+
+char *env_getenv(const char *name)
+{
+ cfe_envvar_t *env;
+
+ env = env_findenv(name);
+
+ if (env) {
+ return env->value;
+ }
+
+ return NULL;
+}
+
+
+/* *********************************************************************
+ * env_setenv(name,value,flags)
+ *
+ * Set the value of an environment variable
+ *
+ * Input parameters:
+ * name - name of variable
+ * value - value of variable
+ * flags - flags for variable (ENV_FLG_xxx)
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int env_setenv(const char *name,char *value,int flags)
+{
+ cfe_envvar_t *env;
+ int namelen;
+
+ env = env_findenv(name);
+ if (env) {
+ if (!(flags & ENV_FLG_ADMIN)) {
+ if (env->flags & ENV_FLG_READONLY) return CFE_ERR_ENVREADONLY;
+ }
+ q_dequeue((queue_t *) env);
+ KFREE(env);
+ }
+
+ namelen = strlen(name);
+
+ env = KMALLOC(sizeof(cfe_envvar_t) + namelen + 1 + strlen(value) + 1,0);
+ if (!env) return CFE_ERR_NOMEM;
+
+ env->name = (char *) (env+1);
+ env->value = env->name + namelen + 1;
+ env->flags = (flags & ENV_FLG_MASK);
+
+ strcpy(env->name,name);
+ strcpy(env->value,value);
+
+ q_enqueue(&env_envvars,(queue_t *) env);
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * env_load()
+ *
+ * Load the environment from the NVRAM device.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+
+int env_load(void)
+{
+ int size;
+ unsigned char *buffer;
+ unsigned char *ptr;
+ unsigned char *envval;
+ unsigned int reclen;
+ unsigned int rectype;
+ int offset;
+ int flg;
+ int retval = -1;
+ char valuestr[256];
+
+ /*
+ * If in 'safe mode', don't read the environment the first time.
+ */
+
+ if (cfe_startflags & CFE_INIT_SAFE) {
+ cfe_startflags &= ~CFE_INIT_SAFE;
+ return 0;
+ }
+
+ flg = nvram_open();
+ if (flg < 0) return flg;
+
+ size = nvram_getsize();
+ buffer = KMALLOC(size,0);
+
+ if (buffer == NULL) return CFE_ERR_NOMEM;
+
+ ptr = buffer;
+ offset = 0;
+
+ /* Read the record type and length */
+ if (nvram_read(ptr,offset,1) != 1) {
+ retval = CFE_ERR_IOERR;
+ goto error;
+ }
+
+ while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) {
+
+ /* Adjust pointer for TLV type */
+ rectype = *(ptr);
+ offset++;
+ size--;
+
+ /*
+ * Read the length. It can be either 1 or 2 bytes
+ * depending on the code
+ */
+ if (rectype & ENV_LENGTH_8BITS) {
+ /* Read the record type and length - 8 bits */
+ if (nvram_read(ptr,offset,1) != 1) {
+ retval = CFE_ERR_IOERR;
+ goto error;
+ }
+ reclen = *(ptr);
+ size--;
+ offset++;
+ }
+ else {
+ /* Read the record type and length - 16 bits, MSB first */
+ if (nvram_read(ptr,offset,2) != 2) {
+ retval = CFE_ERR_IOERR;
+ goto error;
+ }
+ reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1);
+ size -= 2;
+ offset += 2;
+ }
+
+ if (reclen > size) break; /* should not happen, bad NVRAM */
+
+ switch (rectype) {
+ case ENV_TLV_TYPE_ENV:
+ /* Read the TLV data */
+ if (nvram_read(ptr,offset,reclen) != reclen) goto error;
+ flg = *ptr++;
+ envval = (unsigned char *) strnchr(ptr,'=',(reclen-1));
+ if (envval) {
+ *envval++ = '\0';
+ memcpy(valuestr,envval,(reclen-1)-(envval-ptr));
+ valuestr[(reclen-1)-(envval-ptr)] = '\0';
+ env_setenv(ptr,valuestr,flg);
+ }
+ break;
+
+ default:
+ /* Unknown TLV type, skip it. */
+ break;
+ }
+
+ /*
+ * Advance to next TLV
+ */
+
+ size -= (int)reclen;
+ offset += reclen;
+
+ /* Read the next record type */
+ ptr = buffer;
+ if (nvram_read(ptr,offset,1) != 1) goto error;
+ }
+
+ retval = 0; /* success! */
+
+error:
+ KFREE(buffer);
+ nvram_close();
+
+ return retval;
+
+}
+
+
+/* *********************************************************************
+ * env_save()
+ *
+ * Write the environment to the NVRAM device.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+int env_save(void)
+{
+ int size;
+ unsigned char *buffer;
+ unsigned char *buffer_end;
+ unsigned char *ptr;
+ queue_t *qb;
+ cfe_envvar_t *env;
+ int namelen;
+ int valuelen;
+ int flg;
+
+ flg = nvram_open();
+ if (flg < 0) return flg;
+
+ nvram_erase();
+
+ size = nvram_getsize();
+ buffer = KMALLOC(size,0);
+
+ if (buffer == NULL) return CFE_ERR_NOMEM;
+
+ buffer_end = buffer + size;
+
+ ptr = buffer;
+
+ for (qb = env_envvars.q_next; qb != &env_envvars; qb = qb->q_next) {
+ env = (cfe_envvar_t *) qb;
+
+ if (env->flags & (ENV_FLG_BUILTIN)) continue;
+
+ namelen = strlen(env->name);
+ valuelen = strlen(env->value);
+
+ if ((ptr + 2 + namelen + valuelen + 1 + 1 + 1) > buffer_end) break;
+
+ *ptr++ = ENV_TLV_TYPE_ENV; /* TLV record type */
+ *ptr++ = (namelen + valuelen + 1 + 1); /* TLV record length */
+
+ *ptr++ = (unsigned char)env->flags;
+ memcpy(ptr,env->name,namelen); /* TLV record data */
+ ptr += namelen;
+ *ptr++ = '=';
+ memcpy(ptr,env->value,valuelen);
+ ptr += valuelen;
+
+ }
+
+ *ptr++ = ENV_TLV_TYPE_END;
+
+ size = nvram_write(buffer,0,ptr-buffer);
+
+ KFREE(buffer);
+
+ nvram_close();
+
+ return (size == (ptr-buffer)) ? 0 : CFE_ERR_IOERR;
+}
diff --git a/cfe/cfe/main/nvram_subr.c b/cfe/cfe/main/nvram_subr.c
new file mode 100644
index 0000000..2c44bca
--- /dev/null
+++ b/cfe/cfe/main/nvram_subr.c
@@ -0,0 +1,300 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * NVRAM subroutines File: nvram_subr.c
+ *
+ * High-level routines to read/write the NVRAM device.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_ioctl.h"
+
+#include "cfe_error.h"
+#include "env_subr.h"
+#include "nvram_subr.h"
+#include "cfe.h"
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+static int nvram_handle = -1;
+static nvram_info_t nvram_info;
+static char *nvram_devname = NULL;
+
+/* *********************************************************************
+ * nvram_getinfo(info)
+ *
+ * Obtain information about the NVRAM device from the device
+ * driver. A flash device might only dedicate a single sector
+ * to the environment, so we need to ask the driver first.
+ *
+ * Input parameters:
+ * info - nvram info
+ *
+ * Return value:
+ * 0 if ok
+ * <0 = error code
+ ********************************************************************* */
+
+static int nvram_getinfo(nvram_info_t *info)
+{
+ int retlen;
+
+ if (nvram_handle == -1) return -1;
+
+ cfe_ioctl(nvram_handle,IOCTL_NVRAM_UNLOCK,NULL,0,NULL,0);
+
+ if (cfe_ioctl(nvram_handle,IOCTL_NVRAM_GETINFO,
+ (unsigned char *) info,
+ sizeof(nvram_info_t),
+ &retlen,0) != 0) {
+ return -1;
+ }
+
+ return 0;
+
+}
+
+/* *********************************************************************
+ * nvram_open()
+ *
+ * Open the default NVRAM device and get the information from the
+ * device driver.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int nvram_open(void)
+{
+ if (nvram_handle != -1) {
+ nvram_close();
+ }
+
+ if (nvram_devname == NULL) {
+ return CFE_ERR_DEVNOTFOUND;
+ }
+
+ nvram_handle = cfe_open(nvram_devname);
+
+ if (nvram_handle < 0) {
+ return CFE_ERR_DEVNOTFOUND;
+ }
+
+ if (nvram_getinfo(&nvram_info) < 0) {
+ nvram_close();
+ return CFE_ERR_IOERR;
+ }
+
+ return 0;
+}
+
+/* *********************************************************************
+ * nvram_close()
+ *
+ * Close the NVRAM device
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+int nvram_close(void)
+{
+ if (nvram_handle != -1) {
+ cfe_close(nvram_handle);
+ nvram_handle = -1;
+ }
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * nvram_getsize()
+ *
+ * Return the total size of the NVRAM device. Note that
+ * this is the total size that is used for the NVRAM functions,
+ * not the size of the underlying media.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * size. <0 if error
+ ********************************************************************* */
+
+int nvram_getsize(void)
+{
+ if (nvram_handle < 0) return 0;
+ return nvram_info.nvram_size;
+}
+
+
+/* *********************************************************************
+ * nvram_read(buffer,offset,length)
+ *
+ * Read data from the NVRAM device
+ *
+ * Input parameters:
+ * buffer - destination buffer
+ * offset - offset of data to read
+ * length - number of bytes to read
+ *
+ * Return value:
+ * number of bytes read, or <0 if error occured
+ ********************************************************************* */
+int nvram_read(unsigned char *buffer,int offset,int length)
+{
+ if (nvram_handle == -1) return -1;
+
+ return cfe_readblk(nvram_handle,
+ (cfe_offset_t) (offset+nvram_info.nvram_offset),
+ buffer,
+ length);
+}
+
+/* *********************************************************************
+ * nvram_write(buffer,offset,length)
+ *
+ * Write data to the NVRAM device
+ *
+ * Input parameters:
+ * buffer - source buffer
+ * offset - offset of data to write
+ * length - number of bytes to write
+ *
+ * Return value:
+ * number of bytes written, or -1 if error occured
+ ********************************************************************* */
+int nvram_write(unsigned char *buffer,int offset,int length)
+{
+ if (nvram_handle == -1) return -1;
+
+ return cfe_writeblk(nvram_handle,
+ (cfe_offset_t) (offset+nvram_info.nvram_offset),
+ buffer,
+ length);
+}
+
+
+/* *********************************************************************
+ * nvram_erase()
+ *
+ * Erase the NVRAM device. Not all devices need to be erased,
+ * but flash memory does.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int nvram_erase(void)
+{
+ int retlen;
+
+ if (nvram_handle < 0) {
+ return -1;
+ }
+
+ if (nvram_info.nvram_eraseflg == FALSE) return 0;
+
+ if (cfe_ioctl(nvram_handle,IOCTL_NVRAM_ERASE,
+ (unsigned char *) &nvram_info,
+ sizeof(nvram_info_t),
+ &retlen,0) != 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * cfe_set_envdevice(name)
+ *
+ * Set the environment NVRAM device name
+ *
+ * Input parameters:
+ * name - name of device to use for NVRAM
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int cfe_set_envdevice(char *name)
+{
+ int res;
+
+ nvram_devname = strdup(name);
+
+ res = nvram_open();
+
+ if (res != 0) {
+ xprintf("!! Could not open NVRAM device %s\n",nvram_devname);
+ return res;
+ }
+
+ nvram_close();
+
+ res = env_load();
+
+ return res;
+}
diff --git a/cfe/cfe/main/nvram_subr.h b/cfe/cfe/main/nvram_subr.h
new file mode 100644
index 0000000..f614ec2
--- /dev/null
+++ b/cfe/cfe/main/nvram_subr.h
@@ -0,0 +1,54 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * NVRAM prototypes File: nvram_subr.h
+ *
+ * Prototypes for NVRAM routines.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+int nvram_getsize(void);
+int nvram_read(unsigned char *buffer,int,int);
+int nvram_write(unsigned char *buffer,int,int);
+int nvram_open(void);
+int nvram_close(void);
+int nvram_erase(void);
+
diff --git a/cfe/cfe/net/README b/cfe/cfe/net/README
new file mode 100644
index 0000000..f4c1c8c
--- /dev/null
+++ b/cfe/cfe/net/README
@@ -0,0 +1,17 @@
+
+This directory contains the network modules for CFE. The
+following standards are implemented here:
+
+* Ethernet datalink
+* ARP
+* IP
+* UDP
+* ICMP
+* TFTP
+* BOOTP/DHCP
+* DNS (for queries only)
+* TCP
+
+If anyone really screams for it, I've considered putting a simple
+(very simple) TCP stack in here as well, but it doesn't seem worth it.
+
diff --git a/cfe/cfe/net/dev_tcpconsole.c b/cfe/cfe/net/dev_tcpconsole.c
new file mode 100644
index 0000000..43b4f1c
--- /dev/null
+++ b/cfe/cfe/net/dev_tcpconsole.c
@@ -0,0 +1,341 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * TCP Console Driver File: dev_tcpconsole.c
+ *
+ * Evil hack: A console driver that uses a TCP socket.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+#include "addrspace.h"
+
+#include "cfe_timer.h"
+
+#include "bsp_config.h"
+
+#if CFG_TCP
+#include "net_ebuf.h"
+#include "net_api.h"
+
+/*
+ * Friendly warning: Don't put printfs in here or enable any
+ * debugging messages in the TCP stack if you're really
+ * going to use this for your console device. You'll end up
+ * with a recursion loop!
+ */
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define TCPCONSOLE_DEFAULT_PORT 23 /* telnet */
+
+/* *********************************************************************
+ * Forward
+ ********************************************************************* */
+
+static void tcpconsole_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+static int tcpconsole_open(cfe_devctx_t *ctx);
+static int tcpconsole_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int tcpconsole_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int tcpconsole_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int tcpconsole_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int tcpconsole_close(cfe_devctx_t *ctx);
+
+const static cfe_devdisp_t tcpconsole_dispatch = {
+ tcpconsole_open,
+ tcpconsole_read,
+ tcpconsole_inpstat,
+ tcpconsole_write,
+ tcpconsole_ioctl,
+ tcpconsole_close,
+ NULL,
+ NULL
+};
+
+const cfe_driver_t tcpconsole = {
+ "TCP Console",
+ "tcpconsole",
+ CFE_DEV_SERIAL,
+ &tcpconsole_dispatch,
+ tcpconsole_probe
+};
+
+
+/* *********************************************************************
+ * tcpconsole structure
+ ********************************************************************* */
+
+/*
+ * States our connection can be in
+ */
+
+#define TCPCONSTAT_IDLE 0
+#define TCPCONSTAT_LISTEN 1
+#define TCPCONSTAT_CONNECTED 2
+#define TCPCONSTAT_DISCONNECTED 3
+#define TCPCONSTAT_BROKEN 4
+
+/*
+ * state information
+ */
+
+typedef struct tcpconsole_s {
+ int tcp_socket;
+ int tcp_status;
+ int tcp_port;
+} tcpconsole_t;
+
+
+static void tcpconsole_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ tcpconsole_t *softc;
+ char descr[80];
+
+ softc = (tcpconsole_t *) KMALLOC(sizeof(tcpconsole_t),0);
+ if (softc) {
+ softc->tcp_socket = -1;
+ softc->tcp_status = TCPCONSTAT_IDLE;
+ xsprintf(descr, "%s", drv->drv_description);
+
+ if (probe_a == 0) probe_a = TCPCONSOLE_DEFAULT_PORT;
+
+ softc->tcp_port = (int)probe_a;
+
+ cfe_attach(drv, softc, NULL, descr);
+ }
+}
+
+
+static int tcpconsole_isready(tcpconsole_t *softc,int *rxbytes)
+{
+ int res;
+ int connstat,rxeof;
+
+ res = tcp_status(softc->tcp_socket,&connstat,rxbytes,&rxeof);
+
+ /*
+ * Return:
+ * -1 if we could not get status
+ * 0 if we are not connected or are connected and at EOF
+ * 1 if we are connected.
+ */
+
+ if (res < 0) return res;
+ if (connstat != TCPSTATUS_CONNECTED) return 0;
+ if (!rxeof) return 1;
+
+ return 0;
+}
+
+
+static int tcpconsole_process(tcpconsole_t *softc)
+{
+ int res = 0;
+
+ switch (softc->tcp_status) {
+ case TCPCONSTAT_IDLE:
+ /* Idle, set up listening socket */
+ res = tcp_socket();
+ if (res < 0) {
+ softc->tcp_status = TCPCONSTAT_BROKEN;
+ return res;
+ }
+ softc->tcp_socket = res;
+
+ res = tcp_listen(softc->tcp_socket,softc->tcp_port);
+
+ if (res < 0) {
+ tcp_close(softc->tcp_socket);
+ softc->tcp_status = TCPCONSTAT_BROKEN;
+ softc->tcp_socket = -1;
+ return res;
+ }
+ softc->tcp_status = TCPCONSTAT_LISTEN;
+ break;
+
+ case TCPCONSTAT_LISTEN:
+ /* Still waiting for a connection */
+ res = 0;
+ if (tcpconsole_isready(softc,NULL) > 0) {
+ softc->tcp_status = TCPCONSTAT_CONNECTED;
+ }
+ break;
+
+ case TCPCONSTAT_CONNECTED:
+ res = 0; /* do nothing, we're okay */
+ break;
+
+ case TCPCONSTAT_DISCONNECTED:
+ /* Currently connected, kill off this connection */
+ tcp_close(softc->tcp_socket);
+ softc->tcp_socket = -1;
+ softc->tcp_status = TCPCONSTAT_IDLE;
+ break;
+
+ case TCPCONSTAT_BROKEN:
+ /* Broken. Stay broken. */
+ res = 0;
+ break;
+ }
+
+ return res;
+}
+
+
+static int tcpconsole_open(cfe_devctx_t *ctx)
+{
+ return 0;
+}
+
+static int tcpconsole_read(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ tcpconsole_t *softc = ctx->dev_softc;
+ unsigned char *bptr;
+ int blen;
+ int res;
+
+ POLL();
+ tcpconsole_process(softc);
+
+ buffer->buf_retlen = 0;
+
+ if (softc->tcp_status == TCPCONSTAT_CONNECTED) {
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+
+ if (tcpconsole_isready(softc,NULL) <= 0) {
+ softc->tcp_status = TCPCONSTAT_DISCONNECTED;
+ return 0;
+ }
+
+ res = tcp_recv(softc->tcp_socket,bptr,blen);
+
+ if (res > 0) {
+ buffer->buf_retlen = res;
+ }
+ }
+
+ return 0;
+}
+
+static int tcpconsole_inpstat(cfe_devctx_t *ctx, iocb_inpstat_t *inpstat)
+{
+ tcpconsole_t *softc = ctx->dev_softc;
+ unsigned int rxbytes;
+
+ POLL();
+ tcpconsole_process(softc);
+
+ inpstat->inp_status = 0;
+
+ if (softc->tcp_status == TCPCONSTAT_CONNECTED) {
+ if (tcpconsole_isready(softc,&rxbytes) <= 0) {
+ softc->tcp_status = TCPCONSTAT_DISCONNECTED;
+ }
+ else {
+ inpstat->inp_status = (rxbytes > 0);
+ }
+ }
+
+ return 0;
+}
+
+static int tcpconsole_write(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ tcpconsole_t *softc = ctx->dev_softc;
+ unsigned char *bptr;
+ int blen;
+ int res;
+
+ POLL();
+ tcpconsole_process(softc);
+
+ buffer->buf_retlen = 0;
+
+ if (softc->tcp_status == TCPCONSTAT_CONNECTED) {
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+
+ if (tcpconsole_isready(softc,NULL) <= 0) {
+ softc->tcp_status = TCPCONSTAT_DISCONNECTED;
+ return 0;
+ }
+
+ res = tcp_send(softc->tcp_socket,bptr,blen);
+
+ if (res > 0) {
+ buffer->buf_retlen = res;
+ }
+ }
+
+ return 0;
+}
+
+static int tcpconsole_ioctl(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ return -1;
+}
+
+static int tcpconsole_close(cfe_devctx_t *ctx)
+{
+ tcpconsole_t *softc = ctx->dev_softc;
+
+ if (softc->tcp_status == TCPCONSTAT_CONNECTED) {
+ softc->tcp_status = TCPCONSTAT_DISCONNECTED;
+ }
+
+ return 0;
+}
+
+
+#endif
diff --git a/cfe/cfe/net/mii.h b/cfe/cfe/net/mii.h
new file mode 100644
index 0000000..ac56958
--- /dev/null
+++ b/cfe/cfe/net/mii.h
@@ -0,0 +1,187 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * MII register definitions File: mii.h
+ *
+ * Register and bit definitions for the standard MII management
+ * interface.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifndef _MII_H_
+#define _MII_H_
+
+/* Access/command codes */
+
+#define MII_COMMAND_START 0x01
+#define MII_COMMAND_READ 0x02
+#define MII_COMMAND_WRITE 0x01
+#define MII_COMMAND_ACK 0x02
+
+
+/* Registers */
+
+#define MII_BMCR 0x00 /* Basic Mode Control (rw) */
+#define MII_BMSR 0x01 /* Basic Mode Status (ro) */
+#define MII_PHYIDR1 0x02
+#define MII_PHYIDR2 0x03
+#define MII_ANAR 0x04 /* Autonegotiation Advertisement */
+#define MII_ANLPAR 0x05 /* Autonegotiation Link Partner Ability (rw) */
+#define MII_ANER 0x06 /* Autonegotiation Expansion */
+#define MII_K1CTL 0x09 /* 1000baseT control */
+#define MII_K1STSR 0x0A /* 1K Status Register (ro) */
+#define MII_AUXCTL 0x18 /* aux control register */
+
+
+/* Basic Mode Control register (RW) */
+
+#define BMCR_RESET 0x8000
+#define BMCR_LOOPBACK 0x4000
+#define BMCR_SPEED0 0x2000
+#define BMCR_ANENABLE 0x1000
+#define BMCR_POWERDOWN 0x0800
+#define BMCR_ISOLATE 0x0400
+#define BMCR_RESTARTAN 0x0200
+#define BMCR_DUPLEX 0x0100
+#define BMCR_COLTEST 0x0080
+#define BMCR_SPEED1 0x0040
+#define BMCR_SPEED1000 (BMCR_SPEED1)
+#define BMCR_SPEED100 (BMCR_SPEED0)
+#define BMCR_SPEED10 0
+
+
+/* Basic Mode Status register (RO) */
+
+#define BMSR_100BT4 0x8000
+#define BMSR_100BT_FDX 0x4000
+#define BMSR_100BT_HDX 0x2000
+#define BMSR_10BT_FDX 0x1000
+#define BMSR_10BT_HDX 0x0800
+#define BMSR_100BT2_FDX 0x0400
+#define BMSR_100BT2_HDX 0x0200
+#define BMSR_1000BT_XSR 0x0100
+#define BMSR_PRESUP 0x0040
+#define BMSR_ANCOMPLETE 0x0020
+#define BMSR_REMFAULT 0x0010
+#define BMSR_AUTONEG 0x0008
+#define BMSR_LINKSTAT 0x0004
+#define BMSR_JABDETECT 0x0002
+#define BMSR_EXTCAPAB 0x0001
+
+
+/* PHY Identifer registers (RO) */
+
+#define PHYIDR1 0x2000
+#define PHYIDR2 0x5C60
+
+
+/* Autonegotiation Advertisement register (RW) */
+
+#define ANAR_NP 0x8000
+#define ANAR_RF 0x2000
+#define ANAR_ASYPAUSE 0x0800
+#define ANAR_PAUSE 0x0400
+#define ANAR_T4 0x0200
+#define ANAR_TXFD 0x0100
+#define ANAR_TXHD 0x0080
+#define ANAR_10FD 0x0040
+#define ANAR_10HD 0x0020
+#define ANAR_PSB 0x001F
+
+#define PSB_802_3 0x0001 /* 802.3 */
+
+/* Autonegotiation Link Partner Abilities register (RW) */
+
+#define ANLPAR_NP 0x8000
+#define ANLPAR_ACK 0x4000
+#define ANLPAR_RF 0x2000
+#define ANLPAR_ASYPAUSE 0x0800
+#define ANLPAR_PAUSE 0x0400
+#define ANLPAR_T4 0x0200
+#define ANLPAR_TXFD 0x0100
+#define ANLPAR_TXHD 0x0080
+#define ANLPAR_10FD 0x0040
+#define ANLPAR_10HD 0x0020
+#define ANLPAR_PSB 0x001F
+
+
+/* Autonegotiation Expansion register (RO) */
+
+#define ANER_PDF 0x0010
+#define ANER_LPNPABLE 0x0008
+#define ANER_NPABLE 0x0004
+#define ANER_PAGERX 0x0002
+#define ANER_LPANABLE 0x0001
+
+
+#define ANNPTR_NP 0x8000
+#define ANNPTR_MP 0x2000
+#define ANNPTR_ACK2 0x1000
+#define ANNPTR_TOGTX 0x0800
+#define ANNPTR_CODE 0x0008
+
+#define ANNPRR_NP 0x8000
+#define ANNPRR_MP 0x2000
+#define ANNPRR_ACK3 0x1000
+#define ANNPRR_TOGTX 0x0800
+#define ANNPRR_CODE 0x0008
+
+
+#define K1TCR_TESTMODE 0x0000
+#define K1TCR_MSMCE 0x1000
+#define K1TCR_MSCV 0x0800
+#define K1TCR_RPTR 0x0400
+#define K1TCR_1000BT_FDX 0x200
+#define K1TCR_1000BT_HDX 0x100
+
+#define K1STSR_MSMCFLT 0x8000
+#define K1STSR_MSCFGRES 0x4000
+#define K1STSR_LRSTAT 0x2000
+#define K1STSR_RRSTAT 0x1000
+#define K1STSR_LP1KFD 0x0800
+#define K1STSR_LP1KHD 0x0400
+#define K1STSR_LPASMDIR 0x0200
+
+#define K1SCR_1KX_FDX 0x8000
+#define K1SCR_1KX_HDX 0x4000
+#define K1SCR_1KT_FDX 0x2000
+#define K1SCR_1KT_HDX 0x1000
+
+#endif /* _MII_H_ */
diff --git a/cfe/cfe/net/net_api.c b/cfe/cfe/net/net_api.c
new file mode 100755
index 0000000..c9f119e
--- /dev/null
+++ b/cfe/cfe/net/net_api.c
@@ -0,0 +1,1095 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Top-level API to network File: net_api.c
+ *
+ * This routine contains the highest-level API to the network
+ * routines. The global handle to the network state is right here.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "bsp_config.h"
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_ioctl.h"
+#include "cfe_timer.h"
+
+#include "cfe_error.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+
+#include "cfe_timer.h"
+
+#include "net_ip.h"
+#include "net_ip_internal.h"
+#include "net_api.h"
+
+#include "env_subr.h"
+
+#if CFG_TCP
+#include "net_tcp.h"
+#endif
+
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+/*
+ * Net context. All the soft context structures of all the
+ * layers of the network stack are bundled here. There's only one
+ * of these in the system when the network is active.
+ */
+
+typedef struct net_ctx_s {
+ /* Global info */
+ int64_t timer;
+
+ /* device name */
+ char *devname;
+
+ /* Run-time info for IP interface */
+ ip_info_t *ipinfo;
+
+ /* Info for Ethernet interface */
+ ether_info_t *ethinfo;
+
+ /* Info specific to UDP */
+ udp_info_t *udpinfo;
+
+ /* Info specific to ICMP */
+ icmp_info_t *icmpinfo;
+
+#if CFG_TCP
+ /* Info specific to TCP */
+ tcp_info_t *tcpinfo;
+#endif
+} net_ctx_t;
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+/* Foxconn add start by Cliff Wang, 03/23/2010 */
+net_ctx_t *netctx = NULL;
+// static net_ctx_t *netctx = NULL;
+/* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+/* *********************************************************************
+ * UDP INTERFACE
+ ********************************************************************* */
+
+/* *********************************************************************
+ * udp_alloc()
+ *
+ * Allocate an ebuf with fields reserved for the UDP layer.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * pointer to ebuf, or NULL if no EBUFs are available
+ ********************************************************************* */
+
+ebuf_t *udp_alloc(void)
+{
+ if (!netctx) return NULL;
+ return _udp_alloc(netctx->udpinfo);
+}
+
+/* *********************************************************************
+ * udp_free(buf)
+ *
+ * Return an ebuf to the pool. The ebuf was presumably allocated
+ * via udp_alloc() first.
+ *
+ * Input parameters:
+ * buf - ebuf to return to the pool
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+void udp_free(ebuf_t *buf)
+{
+ if (!netctx) return;
+ _udp_free(netctx->udpinfo,buf);
+}
+
+/* *********************************************************************
+ * udp_socket(port)
+ *
+ * Open a UDP socket. Once open, datagrams sent on the socket will
+ * go to the specified port number. You can change the port later
+ * using the "udp_connect" function.
+ *
+ * Input parameters:
+ * port - port number
+ *
+ * Return value:
+ * UDP port handle, or -1 if no ports are available.
+ ********************************************************************* */
+
+int udp_socket(uint16_t port)
+{
+ if (!netctx) return -1;
+
+ return _udp_socket(netctx->udpinfo,port);
+}
+
+/* *********************************************************************
+ * udp_close(sock)
+ *
+ * Close a udp socket. You pass this handle returned from a previous
+ * call to udp_open.
+ *
+ * Input parameters:
+ * handle - UDP port handle, from udp_open()
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void udp_close(int portnum)
+{
+ if (!netctx) return;
+
+ _udp_close(netctx->udpinfo,portnum);
+}
+
+
+/* *********************************************************************
+ * udp_send(s,buf,dest)
+ *
+ * Send a datagram to the specified destination address. The
+ * source and destination UDP port numbers are taken from the
+ * values passed to earlier calls to udp_open, udp_bind, and
+ * udp_connect.
+ *
+ * Input parameters:
+ * s - socket handle, from udp_open
+ * buf - ebuf to send (allocated via udp_alloc)
+ * dest - pointer to 4-byte destination IP address
+ *
+ * Return value:
+ * 0 if ok
+ * <0 if an error occured.
+ ********************************************************************* */
+
+int udp_send(int s,ebuf_t *buf,uint8_t *dest)
+{
+ if (!netctx) return -1;
+
+ return _udp_send(netctx->udpinfo,s,buf,dest);
+}
+
+/* *********************************************************************
+ * udp_bind(s,port)
+ *
+ * Re-"bind" the specified udp socket to a new source port.
+ * This changes the source port number that will be transmitted
+ * in subsequent calls to udp_send()
+ *
+ * Input parameters:
+ * s - socket handle
+ * port - new port number
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+int udp_bind(int s,uint16_t port)
+{
+ if (!netctx) return -1;
+
+ return _udp_bind(netctx->udpinfo,s,port);
+}
+
+
+/* *********************************************************************
+ * udp_connect(s,port)
+ *
+ * Set the port number to be used in the destination port field
+ * for subsequent calls to udp_send().
+ *
+ * Input parameters:
+ * s - udp socket handle
+ * port - new destination port number
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+int udp_connect(int s,uint16_t port)
+{
+ if (!netctx) return -1;
+
+ return _udp_connect(netctx->udpinfo,s,port);
+}
+
+/* *********************************************************************
+ * udp_recv(s)
+ *
+ * Return the next packet from the receive queue for this port.
+ * If no packets are available, NULL is returned.
+ *
+ * Input parameters:
+ * s - udp port handle
+ *
+ * Return value:
+ * ebuf (if a packet is available)
+ * NULL (no packet available)
+ ********************************************************************* */
+
+ebuf_t *udp_recv(int s)
+{
+ if (!netctx) return NULL;
+
+ return _udp_recv(netctx->udpinfo,s);
+}
+
+
+/* *********************************************************************
+ * udp_recv_with_timeout(s,seconds)
+ *
+ * Return the next packet from the receive queue for this socket,
+ * waiting for one to arrive if there are none available.
+ *
+ * Input parameters:
+ * s - udp socket handle
+ * seconds - number of seconds to wait
+ *
+ * Return value:
+ * ebuf (if a packet is available)
+ * NULL (no packet available after timeout)
+ ********************************************************************* */
+
+ebuf_t *udp_recv_with_timeout(int s,int seconds)
+{
+ ebuf_t *buf = NULL;
+ int64_t timer;
+
+ if (!netctx) return NULL;
+
+ TIMER_SET(timer,seconds*CFE_HZ);
+
+ while (!TIMER_EXPIRED(timer)) {
+ POLL();
+ buf = _udp_recv(netctx->udpinfo,s);
+ if (buf) break;
+ }
+
+ return buf;
+}
+
+
+
+#if CFG_TCP
+/* *********************************************************************
+ * TCP INTERFACE
+ ********************************************************************* */
+
+
+/* *********************************************************************
+ * tcp_socket()
+ *
+ * Create a new TCP port.
+ *
+ * Input parameters:
+ * nothing.
+ *
+ * Return value:
+ * TCP port handle, or <0 if no ports are available.
+ ********************************************************************* */
+
+int tcp_socket(void)
+{
+ if (!netctx) return -1;
+
+ return _tcp_socket(netctx->tcpinfo);
+}
+
+/* *********************************************************************
+ * tcp_connect(handle,dest,port)
+ *
+ * Connect to a remote TCP destination.
+ *
+ * Input parameters:
+ * handle - returned from tcp_create
+ * dest - destination IP address
+ * port - destination port number
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int tcp_connect(int s,uint8_t *dest,uint16_t port)
+{
+ int res;
+ unsigned int flags;
+ unsigned int connflag;
+
+ if (!netctx) return -1;
+
+ /*
+ * Get socket's blocking status
+ * If nonblocking, just call the tcp stack
+ * and return what it returns.
+ */
+
+ res = _tcp_getflags(netctx->tcpinfo,s,&flags);
+ if (res < 0) return res;
+
+ if (flags & TCPFLG_NBIO) {
+ return _tcp_connect(netctx->tcpinfo,s,dest,port);
+ }
+
+ /*
+ * Otherwise, call connect and poll till the status
+ * changes. We want to see a transition to the
+ * CONNECTED state, so we loop while we see "CONNECTING"
+ * and return a status based on what it changes to.
+ */
+
+ res = _tcp_connect(netctx->tcpinfo,s,dest,port);
+ if (res < 0) return res;
+ connflag = TCPSTATUS_NOTCONN;
+
+ for (;;) {
+ POLL();
+
+ res = _tcp_status(netctx->tcpinfo,s,&connflag,NULL,NULL);
+ if (res < 0) break;
+
+ if (connflag == TCPSTATUS_CONNECTING) continue;
+ break;
+ }
+
+ if (connflag != TCPSTATUS_CONNECTED) return CFE_ERR_NOTCONN;
+
+ return res;
+}
+
+/* *********************************************************************
+ * tcp_close(s)
+ *
+ * Disconnect a connection (cleanly)
+ *
+ * Input parameters:
+ * s - handle from tcp_create
+ *
+ * Return value:
+ * 0 if ok
+ * else error
+ ********************************************************************* */
+
+int tcp_close(int s)
+{
+ if (!netctx) return -1;
+
+ return _tcp_close(netctx->tcpinfo,s);
+}
+
+
+
+/* *********************************************************************
+ * tcp_send(s,buf,len)
+ *
+ * Send a buffer to the other TCP, buffering as much data as
+ * will fit in the send buffer.
+ *
+ * Input parameters:
+ * s - port handle, from tcp_open
+ * buf - buffer pointer
+ * len - length of buffer to send
+ *
+ * Return value:
+ * >=0 if ok (number of bytes sent)
+ * <0 if an error occured.
+ ********************************************************************* */
+
+int tcp_send(int s,uint8_t *buf,int len)
+{
+ unsigned int flags;
+ int res;
+ int total = 0;
+
+ if (!netctx) return -1;
+
+ /*
+ * Get socket's blocking status
+ * If nonblocking, just call the tcp stack
+ * and return what it returns.
+ */
+
+ res = _tcp_getflags(netctx->tcpinfo,s,&flags);
+ if (res < 0) return res;
+
+ if (flags & TCPFLG_NBIO) {
+ return _tcp_send(netctx->tcpinfo,s,buf,len);
+ }
+
+ /*
+ * The first time we'll check the return code for an
+ * error so we can pass up the failure.
+ */
+
+ res = _tcp_send(netctx->tcpinfo,s,buf,len);
+ if (res < 0) return res;
+
+ buf += res;
+ len -= res;
+ total += res;
+
+ while (len > 0) {
+ /*
+ * Give the TCP stack and devices a chance to run
+ */
+
+ POLL();
+
+ /*
+ * Try to send some more. If we get an error, get out.
+ * otherwise, keep going till all the data is gone.
+ */
+
+ res = _tcp_send(netctx->tcpinfo,s,buf,len);
+ if (res < 0) break;
+ buf += res;
+ len -= res;
+ total += res;
+ }
+
+ /*
+ * If we sent nothing and have an error, return the error.
+ * Otherwise return the amount of data we sent.
+ */
+ if ((total == 0) && (res < 0)) return res;
+ else return total;
+}
+
+/* *********************************************************************
+ * tcp_recv(s,buf,len)
+ *
+ * Receive data from the remote TCP session
+ *
+ * Input parameters:
+ * s - port handle, from tcp_open
+ * buf - buffer pointer
+ * len - length of buffer to send
+ *
+ * Return value:
+ * >=0 if ok (number of bytes received)
+ * <0 if an error occured.
+ ********************************************************************* */
+
+int tcp_recv(int s,uint8_t *buf,int len)
+{
+ unsigned int flags;
+ int res;
+ int total = 0;
+
+ if (!netctx) return -1;
+
+ /*
+ * Get socket's blocking status
+ * If nonblocking, just call the tcp stack
+ * and return what it returns.
+ */
+
+ res = _tcp_getflags(netctx->tcpinfo,s,&flags);
+ if (res < 0) return res;
+
+ if (flags & TCPFLG_NBIO) {
+ return _tcp_recv(netctx->tcpinfo,s,buf,len);
+ }
+
+ /*
+ * The first time we'll check the return code for an
+ * error so we can pass up the failure.
+ */
+
+ res = _tcp_recv(netctx->tcpinfo,s,buf,len);
+ if (res < 0) return res;
+
+ buf += res;
+ len -= res;
+ total += res;
+
+ while (len > 0) {
+ /*
+ * Give the TCP stack and devices a chance to run
+ */
+
+ POLL();
+
+ /*
+ * Try to receive some more. If we get an error, get out.
+ * otherwise, keep going till all the data is gone.
+ */
+
+ res = _tcp_recv(netctx->tcpinfo,s,buf,len);
+ if (res < 0) break;
+
+ if (res == 0) {
+ _tcp_status(netctx->tcpinfo,s,&flags,NULL,NULL);
+ if (flags != TCPSTATUS_CONNECTED) {
+ res = CFE_ERR_NOTCONN;
+ break;
+ }
+ }
+
+ buf += res;
+ len -= res;
+ total += res;
+ }
+
+ /*
+ * If we sent received and have an error, return the error.
+ * Otherwise return the amount of data we sent.
+ */
+ if ((total == 0) && (res < 0)) return res;
+ else return total;
+
+}
+
+/* *********************************************************************
+ * tcp_bind(s,port)
+ *
+ * Re-"bind" the specified tcp port handle to a new source port.
+ *
+ * Used for listening sockets.
+ *
+ * Input parameters:
+ * s - port handle
+ * port - new port number
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+int tcp_bind(int s,uint16_t port)
+{
+ if (!netctx) return -1;
+
+ return _tcp_bind(netctx->tcpinfo,s,port);
+}
+
+/* *********************************************************************
+ * tcp_peeraddr(s,addr,port)
+ *
+ * Return the address of the remote peer.
+ *
+ * Input parameters:
+ * s - port handle
+ * addr - points to 4-byte buffer to receive IP address
+ * port - points to uint16 to receive port number
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+int tcp_peeraddr(int s,uint8_t *addr,uint16_t *port)
+{
+ if (!netctx) return -1;
+
+ return _tcp_peeraddr(netctx->tcpinfo,s,addr,port);
+}
+
+/* *********************************************************************
+ * tcp_setflags(s,addr,flags)
+ *
+ * Set per-socket flags (nodelay, etc.)
+ *
+ * Input parameters:
+ * s - port handle
+ * flags - flags for this socket
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+int tcp_setflags(int s,unsigned int flags)
+{
+ if (!netctx) return -1;
+
+ return _tcp_setflags(netctx->tcpinfo,s,flags);
+}
+
+/* *********************************************************************
+ * tcp_getflags(s,addr,flags)
+ *
+ * Get per-socket flags (nodelay, etc.)
+ *
+ * Input parameters:
+ * s - port handle
+ * flags - flags for this socket
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+int tcp_getflags(int s,unsigned int *flags)
+{
+ if (!netctx) return -1;
+
+ return _tcp_getflags(netctx->tcpinfo,s,flags);
+}
+
+
+/* *********************************************************************
+ * tcp_listen(s)
+ *
+ * Set the socket into "listen" mode.
+ *
+ * Input parameters:
+ * s - port handle
+ * port - port # to listen on
+ *
+ * Return value:
+ * 0 if ok
+ * else error
+ ********************************************************************* */
+
+int tcp_listen(int s,uint16_t port)
+{
+ if (!netctx) return -1;
+
+ return _tcp_listen(netctx->tcpinfo,s,port);
+}
+
+/* *********************************************************************
+ * tcp_status(s,connflag,rxready,rxeof)
+ *
+ * Return the TCP connection's status
+ *
+ * Input parameters:
+ * s - port handle
+ * connflag - points to flag to receive connected status
+ * rxready - returns # of bytes ready to receive
+ * rxeof - returns TRUE if we've been FINed.
+ *
+ * Return value:
+ * 0 if ok
+ * else error
+ ********************************************************************* */
+
+int tcp_status(int s,unsigned int *connflag,int *rxready,int *rxeof)
+{
+ if (!netctx) return -1;
+
+ return _tcp_status(netctx->tcpinfo,s,connflag,rxready,rxeof);
+}
+
+/* *********************************************************************
+ * tcp_debug(s,arg)
+ *
+ * Call the debug routine in the tcp stack.
+ *
+ * Input parameters:
+ * s - socket handle
+ * arg - passed to debug routine
+ *
+ * Return value:
+ * return value from debug routine
+ ********************************************************************* */
+
+int tcp_debug(int s,int arg)
+{
+ if (!netctx) return -1;
+ return _tcp_debug(netctx->tcpinfo,s,arg);
+}
+
+#endif
+
+/* *********************************************************************
+ * ARP FUNCTIONS
+ ********************************************************************* */
+
+
+/* *********************************************************************
+ * arp_add(destip,desthw)
+ *
+ * Add a permanent entry to the ARP table. This entry will
+ * persist until deleted or the interface is deactivated.
+ * This may cause a stale entry to be deleted if the table is full
+ *
+ * Input parameters:
+ * destip - pointer to 4-byte destination IP address
+ * desthw - pointer to 6-byte destination hardware address
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void arp_add(uint8_t *destip,uint8_t *desthw)
+{
+ if (netctx) _arp_add(netctx->ipinfo,destip,desthw);
+}
+
+/* *********************************************************************
+ * arp_lookup(destip)
+ *
+ * Look up the hardware address for an IP address.
+ *
+ * Input parameters:
+ * destip - pointer to 4-byte IP address
+ *
+ * Return value:
+ * pointer to 6-byte hardware address, or NULL if there are
+ * no matching entries in the table.
+ ********************************************************************* */
+
+uint8_t *arp_lookup(uint8_t *destip)
+{
+ if (!netctx) return NULL;
+ return _arp_lookup(netctx->ipinfo,destip);
+}
+
+
+/* *********************************************************************
+ * arp_enumerate(entrynum,ipaddr,hwaddr)
+ *
+ * Return an entry from the ARP table.
+ *
+ * Input parameters:
+ * entrynum - entry number to return, starting with zero
+ * ipaddr - pointer to 4 bytes to receive IP address
+ * hwaddr - pointer to 6 bytes to receive hardware address
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int arp_enumerate(int entrynum,uint8_t *ipaddr,uint8_t *hwaddr)
+{
+ if (!netctx) return -1;
+ return _arp_enumerate(netctx->ipinfo,entrynum,ipaddr,hwaddr);
+}
+
+/* *********************************************************************
+ * arp_delete(ipaddr)
+ *
+ * Delete an entry from the ARP table.
+ *
+ * Input parameters:
+ * ipaddr - pointer to 4-byte IP address
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int arp_delete(uint8_t *ipaddr)
+{
+ if (!netctx) return -1;
+ return _arp_delete(netctx->ipinfo,ipaddr);
+}
+
+/* *********************************************************************
+ * ICMP FUNCTIONS
+ ********************************************************************* */
+
+/* *********************************************************************
+ * icmp_ping(dest,seq,len)
+ *
+ * Ping a remote host, transmitting the ICMP_ECHO message and
+ * waiting for the corresponding ICMP_ECHO_REPLY.
+ *
+ * Input parameters:
+ * dest - pointer to 4-byte destination IP address
+ * seq - sequence number to put in to the ICMP packet
+ * len - length of data to place in ICMP packet
+ *
+ * Return value:
+ * 0 if ok (remote host responded)
+ * else error code
+ ********************************************************************* */
+
+int icmp_ping(uint8_t *dest,int seq,int len)
+{
+ if (!netctx) return -1;
+ return _icmp_ping(netctx->icmpinfo,dest,seq,len);
+}
+
+/* *********************************************************************
+ * INIT/CONFIG FUNCTIONS
+ ********************************************************************* */
+
+/* *********************************************************************
+ * net_getparam(param)
+ *
+ * Return a parameter from the current IP configuration. This is
+ * the main call to set the IP address, netmask, gateway,
+ * name server, host name, etc.
+ *
+ * Input parameters:
+ * param - parameter number (see net_api.h)
+ *
+ * Return value:
+ * pointer to value of parameter, or NULL if parameter
+ * ID is invalid
+ ********************************************************************* */
+
+uint8_t *net_getparam(int param)
+{
+ if (!netctx) return NULL;
+ if (param == NET_DEVNAME) return (uint8_t *) netctx->devname;
+ return _ip_getparam(netctx->ipinfo,param);
+
+}
+
+/* *********************************************************************
+ * net_setparam(param,ptr)
+ *
+ * Set the value of an IP configuration parameter
+ *
+ * Input parameters:
+ * param - parameter number (see net_api.h)
+ * ptr - pointer to parameter's new value
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int net_setparam(int param,uint8_t *ptr)
+{
+ if (!netctx) return NULL;
+ return _ip_setparam(netctx->ipinfo,param,ptr);
+}
+
+/* *********************************************************************
+ * net_poll()
+ *
+ * Process background tasks for the network stack, maintaining
+ * the ARP table, receive queues, etc.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void net_poll(void *arg)
+{
+ if (netctx) {
+ eth_poll(netctx->ethinfo);
+ if (TIMER_EXPIRED(netctx->timer)) {
+ _ip_timer_tick(netctx->ipinfo);
+ TIMER_SET(netctx->timer,CFE_HZ);
+ }
+ }
+}
+
+/* *********************************************************************
+ * net_init(devname)
+ *
+ * Initialize the network interface. This is the main call, once
+ * completed you should call net_setparam to set up the network
+ * addresses and stuff.
+ *
+ * Input parameters:
+ * devname - CFE device name for network device
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int net_init(char *devname)
+{
+ net_ctx_t *ctx;
+
+ if (netctx) net_uninit();
+
+ ctx = KMALLOC(sizeof(net_ctx_t),0);
+
+ if (!ctx) return -1;
+
+ ctx->devname = strdup(devname);
+
+ ctx->ethinfo = eth_init(devname);
+ if (ctx->ethinfo == NULL) {
+ return -1;
+ }
+
+ ctx->ipinfo = _ip_init(ctx->ethinfo);
+ if (ctx->ipinfo == NULL) {
+ eth_uninit(ctx->ethinfo);
+ return -1;
+ }
+
+ ctx->udpinfo = _udp_init(ctx->ipinfo,ctx->ipinfo);
+ if (ctx->udpinfo == NULL) {
+ _ip_uninit(ctx->ipinfo);
+ eth_uninit(ctx->ethinfo);
+ return -1;
+ }
+
+ ctx->icmpinfo = _icmp_init(ctx->ipinfo);
+ if (ctx->icmpinfo == NULL) {
+ _udp_uninit(ctx->udpinfo);
+ _ip_uninit(ctx->ipinfo);
+ eth_uninit(ctx->ethinfo);
+ return -1;
+ }
+
+ cfe_bg_add(net_poll,ctx);
+ TIMER_SET(ctx->timer,CFE_HZ);
+
+#if CFG_TCP
+ ctx->tcpinfo = _tcp_init(ctx->ipinfo,ctx->ipinfo);
+ cfe_bg_add(_tcp_poll,ctx->tcpinfo);
+#endif
+
+ netctx = ctx;
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * net_uninit()
+ *
+ * Uninitialize the network, deallocating all resources allocated
+ * to the network and closing all open device handles
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void net_uninit(void)
+{
+ if (netctx) {
+#if CFG_TCP
+ cfe_bg_remove(_tcp_poll);
+ _tcp_uninit(netctx->tcpinfo);
+#endif
+ TIMER_CLEAR(netctx->timer);
+ _icmp_uninit(netctx->icmpinfo);
+ _udp_uninit(netctx->udpinfo);
+ _ip_uninit(netctx->ipinfo);
+ eth_uninit(netctx->ethinfo);
+ KFREE(netctx->devname);
+ KFREE(netctx);
+ netctx = NULL;
+ cfe_bg_remove(net_poll);
+ }
+}
+
+
+/* *********************************************************************
+ * net_setnetvars()
+ *
+ * Set environment variables related to the network.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void net_setnetvars(void)
+{
+ char *x;
+ uint8_t *addr;
+ char str[60];
+
+ /* Clear out all the environment variables */
+ env_delenv("NET_DEVICE");
+ env_delenv("NET_IPADDR");
+ env_delenv("NET_NETMASK");
+ env_delenv("NET_GATEWAY");
+ env_delenv("NET_NAMESERVER");
+ env_delenv("NET_DOMAIN");
+
+ x = (char *) net_getparam(NET_DEVNAME);
+ if (!x) {
+ return;
+ }
+
+ x = (char *) net_getparam(NET_DEVNAME);
+ if (x) env_setenv("NET_DEVICE",x,ENV_FLG_BUILTIN);
+
+ x = (char *) net_getparam(NET_DOMAIN);
+ if (x) env_setenv("NET_DOMAIN",x,ENV_FLG_BUILTIN);
+
+ addr = net_getparam(NET_IPADDR);
+ if (addr) {
+ xsprintf(str,"%I",addr);
+ env_setenv("NET_IPADDR",str,ENV_FLG_BUILTIN);
+ }
+
+ addr = net_getparam(NET_NETMASK);
+ if (addr) {
+ xsprintf(str,"%I",addr);
+ env_setenv("NET_NETMASK",str,ENV_FLG_BUILTIN);
+ }
+
+ addr = net_getparam(NET_GATEWAY);
+ if (addr) {
+ xsprintf(str,"%I",addr);
+ env_setenv("NET_GATEWAY",str,ENV_FLG_BUILTIN);
+ }
+
+ addr = net_getparam(NET_NAMESERVER);
+ if (addr) {
+ xsprintf(str,"%I",addr);
+ env_setenv("NET_NAMESERVER",str,ENV_FLG_BUILTIN);
+ }
+
+}
+
diff --git a/cfe/cfe/net/net_api.h b/cfe/cfe/net/net_api.h
new file mode 100755
index 0000000..f28b917
--- /dev/null
+++ b/cfe/cfe/net/net_api.h
@@ -0,0 +1,179 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * High-level network API defs File: net_api.h
+ *
+ * This module contains prototypes and constants for the
+ * network (TCP/IP) interface.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#ifndef IP_ADDR_LEN
+#define IP_ADDR_LEN 4
+#endif
+
+/* *********************************************************************
+ * DHCP Protocol
+ ********************************************************************* */
+
+typedef struct dhcpreply_s {
+ uint8_t dr_ipaddr[IP_ADDR_LEN];
+ uint8_t dr_netmask[IP_ADDR_LEN];
+ uint8_t dr_gateway[IP_ADDR_LEN];
+ uint8_t dr_nameserver[IP_ADDR_LEN];
+ uint8_t dr_dhcpserver[IP_ADDR_LEN];
+ uint8_t dr_bootserver[IP_ADDR_LEN];
+ char *dr_hostname;
+ char *dr_domainname;
+ char *dr_bootfile;
+ char *dr_rootpath;
+ char *dr_swapserver;
+ char *dr_script;
+ char *dr_options;
+} dhcpreply_t;
+
+
+int dhcp_bootrequest(dhcpreply_t **reply);
+void dhcp_free_reply(dhcpreply_t *reply);
+void dhcp_set_envvars(dhcpreply_t *reply);
+
+/* *********************************************************************
+ * IP Layer
+ ********************************************************************* */
+
+void ip_uninit(void);
+int ip_init(char *,uint8_t *);
+ebuf_t *ip_alloc(void);
+void ip_free(ebuf_t *buf);
+int ip_send(ebuf_t *buf,uint8_t *destaddr,uint8_t proto);
+uint16_t ip_chksum(uint16_t initchksum,uint8_t *ptr,int len);
+
+/* *********************************************************************
+ * UDP Layer
+ ********************************************************************* */
+
+ebuf_t *udp_alloc(void);
+void udp_free(ebuf_t *buf);
+
+int udp_socket(uint16_t port);
+int udp_bind(int portnum,uint16_t port);
+int udp_connect(int portnum,uint16_t port);
+void udp_close(int portnum);
+int udp_send(int portnum,ebuf_t *buf,uint8_t *dest);
+ebuf_t *udp_recv_with_timeout(int portnum,int seconds);
+ebuf_t *udp_recv(int portnum);
+
+/* *********************************************************************
+ * TCP Layer
+ ********************************************************************* */
+
+#if CFG_TCP
+#ifndef TCPFLG_NODELAY /* XXX should be kept in sync with net_tcp.h */
+#define TCPFLG_NODELAY 1 /* disable nagle */
+#define TCPFLG_NBIO 2 /* non-blocking I/O */
+
+#define TCPSTATUS_NOTCONN 0
+#define TCPSTATUS_CONNECTING 1
+#define TCPSTATUS_CONNECTED 2
+#endif
+int tcp_socket(void);
+void tcp_destroy(int portnum);
+int tcp_connect(int s,uint8_t *dest,uint16_t port);
+int tcp_close(int s);
+int tcp_send(int s,uint8_t *buf,int len);
+int tcp_recv(int s,uint8_t *buf,int len);
+int tcp_bind(int s,uint16_t port);
+int tcp_peeraddr(int s,uint8_t *addr,uint16_t *port);
+int tcp_listen(int s,uint16_t port);
+int tcp_status(int s,unsigned int *connflag,int *rxready,int *rxeof);
+int tcp_debug(int s,int arg);
+int tcp_setflags(int s,unsigned int flags);
+int tcp_getflags(int s,unsigned int *flags);
+#endif
+
+/* *********************************************************************
+ * ARP Layer
+ ********************************************************************* */
+
+uint8_t *arp_lookup(uint8_t *destip);
+void arp_add(uint8_t *destip,uint8_t *desthw);
+int arp_enumerate(int entrynum,uint8_t *ipaddr,uint8_t *hwaddr);
+int arp_delete(uint8_t *ipaddr);
+
+/* *********************************************************************
+ * Network Configuration
+ ********************************************************************* */
+
+#ifndef NET_IPADDR
+#define NET_IPADDR 0
+#define NET_NETMASK 1
+#define NET_GATEWAY 2
+#define NET_NAMESERVER 3
+#define NET_HWADDR 4
+#define NET_DOMAIN 5
+#define NET_HOSTNAME 6
+#define NET_SPEED 7
+#define NET_LOOPBACK 8
+#endif
+#define NET_DEVNAME 10
+
+uint8_t *net_getparam(int param);
+int net_setparam(int param,uint8_t *ptr);
+int net_init(char *devname);
+void net_uninit(void);
+void net_setnetvars(void);
+
+/* *********************************************************************
+ * DNS
+ ********************************************************************* */
+
+int dns_lookup(char *hostname,uint8_t *ipaddr);
+
+/* *********************************************************************
+ * ICMP
+ ********************************************************************* */
+
+int icmp_ping(uint8_t *dest,int seq,int len);
+
diff --git a/cfe/cfe/net/net_arp.c b/cfe/cfe/net/net_arp.c
new file mode 100755
index 0000000..1c12457
--- /dev/null
+++ b/cfe/cfe/net/net_arp.c
@@ -0,0 +1,865 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Address Resolution Protocol File: net_arp.c
+ *
+ * This module implements RFC826, the Address Resolution Protocol.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+
+#include "net_ip.h"
+#include "net_ip_internal.h"
+
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+static int arp_tx_query(ip_info_t *ipi,uint8_t *destaddr);
+static void arp_delete(arpentry_t *ae);
+static void arp_tx_waiting(arpentry_t *ae);
+static arpentry_t *arp_new_entry(ip_info_t *ipi);
+static arpentry_t *arp_find_entry(ip_info_t *ipi,uint8_t *ipaddr);
+static int arp_rx_query(ip_info_t *ipi,uint8_t *srcaddr,
+ uint8_t *targethw,uint8_t *targetip);
+static int arp_rx_response(ip_info_t *ipi,uint8_t *senderhw,
+ uint8_t *senderip);
+static int arp_rx_callback(ebuf_t *buf,void *ref);
+
+
+/* *********************************************************************
+ * arp_tx_query(ipi,destaddr)
+ *
+ * Transmit an ARP QUERY message. ARP QUERY messages are sent
+ * to the Ethernet broadcast address.
+ *
+ * Input parameters:
+ * ipi - IP information
+ * destaddr - IP address to query
+ *
+ * Return value:
+ * 0 - success
+ * <0 - failure
+ ********************************************************************* */
+
+static int arp_tx_query(ip_info_t *ipi,uint8_t *destaddr)
+{
+ ebuf_t *buf;
+ uint8_t hwaddr[ENET_ADDR_LEN];
+
+ /*
+ * Get a buffer.
+ */
+
+ buf = eth_alloc(ipi->eth_info,ipi->arp_port);
+ if (!buf) return -1;
+
+ /*
+ * fill in the fields
+ */
+
+ ebuf_append_u16_be(buf,ARP_HWADDRSPACE_ETHERNET);
+ ebuf_append_u16_be(buf,PROTOSPACE_IP);
+ ebuf_append_u8(buf,ENET_ADDR_LEN);
+ ebuf_append_u8(buf,IP_ADDR_LEN);
+ ebuf_append_u16_be(buf,ARP_OPCODE_REQUEST);
+ ebuf_append_bytes(buf,ipi->arp_hwaddr,ENET_ADDR_LEN);
+ ebuf_append_bytes(buf,ipi->net_info.ip_addr,IP_ADDR_LEN);
+ memset(hwaddr,0,ENET_ADDR_LEN);
+ ebuf_append_bytes(buf,hwaddr,ENET_ADDR_LEN);
+ ebuf_append_bytes(buf,destaddr,IP_ADDR_LEN);
+
+ /*
+ * Transmit the packet
+ */
+
+ eth_send(buf,(uint8_t *)eth_broadcast);
+ eth_free(buf);
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * arp_delete(ae)
+ *
+ * Delete an ARP entry. The usual reason for calling this routine
+ * is to reclaim unused ARP entries, but an ARP entry may be
+ * manually deleted as well.
+ *
+ * Input parameters:
+ * ae - arp entry
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void arp_delete(arpentry_t *ae)
+{
+ ebuf_t *buf;
+
+ /*
+ * Free any buffers associated with the ARP entry.
+ */
+
+ while ((buf = (ebuf_t *) q_deqnext(&(ae->ae_txqueue)))) {
+ eth_free(buf);
+ }
+
+ /*
+ * Reset the important fields
+ */
+
+ ae->ae_timer = 0;
+ ae->ae_usage = 0;
+ ae->ae_retries = 0;
+ ae->ae_state = ae_unused;
+}
+
+
+/* *********************************************************************
+ * _arp_add(ipi,destip,desthw)
+ *
+ * Add a new ARP entry to the ARP table [internal routine]. If
+ * there is no room in the table, some other entry is kicked
+ * out.
+ *
+ * Input parameters:
+ * ipi - IP information
+ * destip - target IP address
+ * desthw - target hardware address
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void _arp_add(ip_info_t *ipi,uint8_t *destip,uint8_t *desthw)
+{
+ arpentry_t *ae;
+
+ ae = arp_find_entry(ipi,desthw);
+ if (!ae) {
+ ae = arp_new_entry(ipi);
+ }
+
+ memcpy(ae->ae_ipaddr,destip,IP_ADDR_LEN);
+ memcpy(ae->ae_ethaddr,desthw,ENET_ADDR_LEN);
+
+ ae->ae_retries = 0;
+ ae->ae_timer = 0; /* keep forever */
+ ae->ae_permanent = TRUE;
+ ae->ae_state = ae_established;
+
+ arp_tx_waiting(ae);
+}
+
+
+/* *********************************************************************
+ * _arp_lookup(ipi,destip)
+ *
+ * Look up an ARP entry [internal routine]. Given an IP address,
+ * return the hardware address to send the packets to, or
+ * NULL if no ARP entry exists.
+ *
+ * Input parameters:
+ * ipi - IP information
+ * destip - destination IP address
+ *
+ * Return value:
+ * pointer to Ethernet hardware address, or NULL if not found
+ ********************************************************************* */
+
+uint8_t *_arp_lookup(ip_info_t *ipi,uint8_t *destip)
+{
+ arpentry_t *ae;
+
+ ae = arp_find_entry(ipi,destip);
+ if (ae == NULL) return NULL;
+
+ return ae->ae_ethaddr;
+}
+
+/* *********************************************************************
+ * _arp_lookup_and_send(ipi,buf,dest)
+ *
+ * Transmit a packet [internal routine]. This routine is called
+ * by the IP layer when it wants to send a packet. We look
+ * through the ARP table to find a suitable destination host and
+ * transmit the packet. If there is no ARP entry, an ARP request
+ * is transmitted and the packet is saved on a queue for when
+ * the address is resolved.
+ *
+ * Input parameters:
+ * ipi - IP information
+ * buf - ebuf to transmit
+ * dest - destination IP address
+ *
+ * Return value:
+ * 0 if ok
+ * <0 if error
+ ********************************************************************* */
+
+int _arp_lookup_and_send(ip_info_t *ipi,ebuf_t *buf,uint8_t *dest)
+{
+ arpentry_t *ae;
+
+ ae = arp_find_entry(ipi,dest);
+
+ if (ae == NULL) {
+ /*
+ * No ARP entry yet, create one and send the query
+ */
+ ae = arp_new_entry(ipi);
+ memcpy(ae->ae_ipaddr,dest,IP_ADDR_LEN);
+ q_enqueue(&(ae->ae_txqueue),(queue_t *) buf);
+ ae->ae_retries = ARP_QUERY_RETRIES;
+ ae->ae_timer = ARP_QUERY_TIMER;
+ ae->ae_state = ae_arping;
+ arp_tx_query(ipi,ae->ae_ipaddr);
+ }
+ else {
+ /*
+ * have an ARP entry. If established, just send the
+ * packet now. Otherwise, queue on arp queue if there's room.
+ */
+ if (ae->ae_state == ae_established) {
+ ae->ae_usage++;
+ if (!ae->ae_permanent) {
+ ae->ae_timer = ARP_KEEP_TIMER;
+ }
+ eth_send(buf,ae->ae_ethaddr);
+ eth_free(buf);
+ }
+ else {
+ if (q_count(&(ae->ae_txqueue)) < ARP_TXWAIT_MAX) {
+ q_enqueue(&(ae->ae_txqueue),(queue_t *) buf);
+ }
+ else {
+ /* no room, silently drop */
+ eth_free(buf);
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* *********************************************************************
+ * arp_tx_waiting(ae)
+ *
+ * Transmit all pending packets on the specified ARP entry's
+ * queue. Packets get queued to an ARP entry when the address
+ * has not completed resolution. Once resolved, this routine
+ * is called to flush the packets out.
+ *
+ * Input parameters:
+ * ae - arp entry
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void arp_tx_waiting(arpentry_t *ae)
+{
+ ebuf_t *buf;
+
+ while ((buf = (ebuf_t *) q_deqnext(&(ae->ae_txqueue)))) {
+ eth_send(buf,ae->ae_ethaddr);
+ eth_free(buf);
+ }
+}
+
+
+/* *********************************************************************
+ * arp_new_entry(ipi)
+ *
+ * Create a new ARP entry, deleting an active entry if necessary.
+ *
+ * Input parameters:
+ * ipi - IP information
+ *
+ * Return value:
+ * arp entry pointer
+ ********************************************************************* */
+
+static arpentry_t *arp_new_entry(ip_info_t *ipi)
+{
+ arpentry_t *ae;
+ arpentry_t *victim = NULL;
+ int idx;
+ int minusage = 0x7FFFFFFF;
+
+ /*
+ * First scan the table and find an empty entry.
+ */
+
+ ae = ipi->arp_table;
+ for (idx = 0; idx < ARP_TABLE_SIZE; idx++,ae++) {
+ if (ae->ae_state == ae_unused) {
+ return ae;
+ }
+ }
+
+ /*
+ * If all entries are in use, pick the one with the
+ * lowest usage count. This isn't very scientific,
+ * and perhaps should use a timer of some sort.
+ */
+
+ ae = ipi->arp_table;
+ for (idx = 0; idx < ARP_TABLE_SIZE; idx++,ae++) {
+ if (ae->ae_usage < minusage) {
+ victim = ae;
+ minusage = ae->ae_usage;
+ }
+ }
+
+ /*
+ * In the highly unlikely event that all entries have
+ * overflow values in their usage counters, just take the
+ * first table entry.
+ */
+
+ if (victim == NULL) victim = ipi->arp_table;
+
+ /*
+ * Clear out the old entry and use it.
+ */
+
+ arp_delete(victim);
+
+ return victim;
+}
+
+/* *********************************************************************
+ * arp_find_entry(ipi,ipaddr)
+ *
+ * Find an ARP entry in the table. Given an IP address, this
+ * routine locates the corresponding ARP table entry. We also
+ * reset the expiration timer for the ARP entry, to prevent
+ * it from from being deleted.
+ *
+ * Input parameters:
+ * ipi - IP info
+ * ipaddr - IP address we're looking for
+ *
+ * Return value:
+ * arp entry pointer, or NULL if not found
+ ********************************************************************* */
+
+static arpentry_t *arp_find_entry(ip_info_t *ipi,uint8_t *ipaddr)
+{
+ arpentry_t *ae;
+ int idx;
+
+ ae = ipi->arp_table;
+
+ for (idx = 0; idx < ARP_TABLE_SIZE; idx++,ae++) {
+ if (ae->ae_state != ae_unused) {
+ if (memcmp(ae->ae_ipaddr,ipaddr,IP_ADDR_LEN) == 0) {
+ if (ae->ae_state == ae_established)
+ ae->ae_timer = ARP_KEEP_TIMER;
+ return ae;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+/* *********************************************************************
+ * arp_rx_query(ipi,srcaddr,targethw,targetip)
+ *
+ * Process a received ARP QUERY message. When we get an ARP,
+ * transmit a reply to the sender.
+ *
+ * Input parameters:
+ * ipi - IP information
+ * srcaddr - source IP address
+ * targethw - target hardware address
+ * targetip - target IP address (should be our address)
+ *
+ * Input parameters:
+ * 0 if ok
+ * else <0 = error
+ ********************************************************************* */
+
+static int arp_rx_query(ip_info_t *ipi,uint8_t *srcaddr,
+ uint8_t *targethw,uint8_t *targetip)
+{
+ ebuf_t *txbuf;
+
+ /*
+ * Allocate a packet and form the reply
+ */
+
+ txbuf = eth_alloc(ipi->eth_info,ipi->arp_port);
+ if (!txbuf) return -1;
+
+ ebuf_append_u16_be(txbuf,ARP_HWADDRSPACE_ETHERNET);
+ ebuf_append_u16_be(txbuf,PROTOSPACE_IP);
+ ebuf_append_u8(txbuf,ENET_ADDR_LEN);
+ ebuf_append_u8(txbuf,IP_ADDR_LEN);
+ ebuf_append_u16_be(txbuf,ARP_OPCODE_REPLY);
+
+ ebuf_append_bytes(txbuf,ipi->arp_hwaddr,ENET_ADDR_LEN);
+ ebuf_append_bytes(txbuf,ipi->net_info.ip_addr,IP_ADDR_LEN);
+
+ ebuf_append_bytes(txbuf,targethw,ENET_ADDR_LEN);
+ ebuf_append_bytes(txbuf,targetip,IP_ADDR_LEN);
+
+ eth_send(txbuf,srcaddr);
+ eth_free(txbuf);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * arp_rx_response(ipi,senderhw,senderip)
+ *
+ * Process a received ARP RESPONSE packet. This packet contains
+ * the hardware address of some host we were querying. Fill
+ * in the rest of the entries in the ARP table and
+ * transmit any pending packets.
+ *
+ * Input parameters:
+ * ipi - IP information
+ * senderhw - sender's hardware address
+ * senderip - sender's IP address
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int arp_rx_response(ip_info_t *ipi,uint8_t *senderhw,uint8_t *senderip)
+{
+ int idx;
+ arpentry_t *ae;
+
+ ae = ipi->arp_table;
+
+ for (idx = 0; idx < ARP_TABLE_SIZE; idx++,ae++) {
+ if (ae->ae_state != ae_unused) {
+ if (memcmp(ae->ae_ipaddr,senderip,IP_ADDR_LEN) == 0) {
+ memcpy(ae->ae_ethaddr,senderhw,ENET_ADDR_LEN);
+ ae->ae_state = ae_established;
+ ae->ae_timer = ARP_KEEP_TIMER;
+ ae->ae_retries = 0;
+ ae->ae_permanent = FALSE;
+ arp_tx_waiting(ae);
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* *********************************************************************
+ * arp_rx_callback(buf,ref)
+ *
+ * Callback for ARP protocol packets. This routine is called
+ * by the datalink layer when we receive an ARP packet. Parse
+ * the packet and call any packet-specific processing routines
+ *
+ * Input parameters:
+ * buf - ebuf that we received
+ * ref - reference data when we opened the port. This is
+ * our IP information structure
+ *
+ * Return value:
+ * ETH_DROP or ETH_KEEP.
+ ********************************************************************* */
+
+static int arp_rx_callback(ebuf_t *buf,void *ref)
+{
+ ip_info_t *ipi = ref;
+ uint16_t t16;
+ uint8_t t8;
+ uint16_t opcode;
+ uint8_t senderip[IP_ADDR_LEN];
+ uint8_t senderhw[ENET_ADDR_LEN];
+ uint8_t targetip[IP_ADDR_LEN];
+ uint8_t targethw[ENET_ADDR_LEN];
+
+ /*
+ * ARP packets have to be at least 28 bytes
+ */
+
+ if (ebuf_length(buf) < 28) goto drop;
+
+ /*
+ * We only do the Ethernet hardware space
+ */
+
+ ebuf_get_u16_be(buf,t16);
+ if (t16 != ARP_HWADDRSPACE_ETHERNET) goto drop;
+
+ /*
+ * We only do the IP protocol space
+ */
+
+ ebuf_get_u16_be(buf,t16);
+ if (t16 != PROTOSPACE_IP) goto drop;
+
+ /*
+ * The IP and Ethernet address lengths had better be right.
+ */
+
+ ebuf_get_u8(buf,t8);
+ if (t8 != ENET_ADDR_LEN) goto drop;
+
+ ebuf_get_u8(buf,t8);
+ if (t8 != IP_ADDR_LEN) goto drop;
+
+ /*
+ * Get the opcode and other fields.
+ */
+
+ ebuf_get_u16_be(buf,opcode);
+
+ ebuf_get_bytes(buf,senderhw,ENET_ADDR_LEN);
+ ebuf_get_bytes(buf,senderip,IP_ADDR_LEN);
+ ebuf_get_bytes(buf,targethw,ENET_ADDR_LEN);
+ ebuf_get_bytes(buf,targetip,IP_ADDR_LEN);
+
+ /*
+ * If it's not for us, just drop it.
+ */
+
+ if (memcmp(targetip,ipi->net_info.ip_addr,IP_ADDR_LEN) != 0) goto drop;
+
+ /*
+ * Dispatch to an appropriate routine.
+ */
+
+ switch (opcode) {
+ case ARP_OPCODE_REQUEST:
+ arp_rx_query(ipi,ebuf_srcaddr(buf),senderhw,senderip);
+ break;
+ case ARP_OPCODE_REPLY:
+ arp_rx_response(ipi,senderhw,senderip);
+ break;
+ }
+
+drop:
+ return ETH_DROP;
+}
+
+/* *********************************************************************
+ * _arp_timer_tick(ipi)
+ *
+ * ARP timer processing [internal routine]. This routine
+ * counts down timer ticks in the ARP entries, causing retransmits
+ * or ARP entry expirations to happen.
+ *
+ * Input parameters:
+ * ipi - IP information
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void _arp_timer_tick(ip_info_t *ipi)
+{
+ int idx;
+ arpentry_t *ae;
+
+ ae = ipi->arp_table;
+
+ /*
+ * Walk through the ARP table.
+ */
+
+ for (idx = 0; idx < ARP_TABLE_SIZE; idx++,ae++) {
+
+ switch (ae->ae_state) {
+ case ae_unused:
+ /*
+ * Unused entry. Do nothing.
+ */
+ break;
+
+ case ae_arping:
+ /*
+ * Entry is arping. Count down the timer, and retransmit
+ * the ARP message.
+ */
+ ae->ae_timer--;
+ if (ae->ae_timer <= 0) {
+ if (ae->ae_retries == 0) {
+ arp_delete(ae);
+ }
+ else {
+ ae->ae_retries--;
+ ae->ae_timer = ARP_QUERY_TIMER;
+ arp_tx_query(ipi,ae->ae_ipaddr);
+ }
+ }
+ break;
+
+ case ae_established:
+ /*
+ * Established entry. Count down the timer and
+ * delete the ARP entry. If the timer is zero
+ * already, it's a permanent ARP entry.
+ */
+ if (ae->ae_timer == 0) break;
+ ae->ae_timer--;
+ if (ae->ae_timer == 0) arp_delete(ae);
+ break;
+ }
+ }
+
+}
+
+/* *********************************************************************
+ * _arp_send_gratuitous(ipi)
+ *
+ * Transmit the "gratuitous arp" (an ARP for our own IP address).
+ * This is done customarily when an interface is initialized.
+ *
+ * Input parameters:
+ * ipi - IP information
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void _arp_send_gratuitous(ip_info_t *ipi)
+{
+ if (!ip_addriszero(ipi->net_info.ip_addr)) {
+ arp_tx_query(ipi,ipi->net_info.ip_addr);
+ }
+}
+
+/* *********************************************************************
+ * _arp_init(ipi)
+ *
+ * Initialize the ARP layer [internal routine]
+ *
+ * Input parameters:
+ * ipi - IP information
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int _arp_init(ip_info_t *ipi)
+{
+ int8_t arpproto[2];
+ int idx;
+ arpentry_t *ae;
+
+ /*
+ * Allocate space for the ARP table
+ */
+
+ ipi->arp_table = KMALLOC(ARP_TABLE_SIZE*sizeof(arpentry_t),0);
+
+ if (ipi->arp_table == NULL) return NULL;
+
+ /*
+ * Initialize the ARP table.
+ */
+
+ ae = ipi->arp_table;
+ for (idx = 0; idx < ARP_TABLE_SIZE; idx++) {
+ ae->ae_state = ae_unused;
+ ae->ae_timer = 0;
+ ae->ae_usage = 0;
+ ae->ae_retries = 0;
+ ae->ae_permanent = 0;
+ q_init(&(ae->ae_txqueue));
+ ae++;
+ }
+
+ /*
+ * Open the Ethernet portal for ARP packets
+ */
+
+ arpproto[0] = (PROTOSPACE_ARP >> 8) & 0xFF;
+ arpproto[1] = (PROTOSPACE_ARP & 0xFF);
+ ipi->arp_port = eth_open(ipi->eth_info,ETH_PTYPE_DIX,arpproto,arp_rx_callback,ipi);
+
+ if (ipi->arp_port < 0) {
+ KFREE(ipi->arp_table);
+ ipi->arp_table = NULL;
+ return -1;
+ }
+
+ /*
+ * Remember our hardware address
+ */
+
+ eth_gethwaddr(ipi->eth_info,ipi->arp_hwaddr);
+
+ /*
+ * Send a query for ourselves if our IP address is set
+ */
+
+ _arp_send_gratuitous(ipi);
+
+ return 0;
+
+}
+
+
+/* *********************************************************************
+ * _arp_uninit(ipi)
+ *
+ * Uninitialize the ARP interface. This is called when the
+ * network module is shut down.
+ *
+ * Input parameters:
+ * ipi - IP information
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void _arp_uninit(ip_info_t *ipi)
+{
+ int idx;
+ arpentry_t *ae;
+
+ /*
+ * Close the Ethernet portal
+ */
+
+ eth_close(ipi->eth_info,ipi->arp_port);
+
+ /*
+ * Clear out the ARP Table.
+ */
+
+ ae = ipi->arp_table;
+ for (idx = 0; idx < ARP_TABLE_SIZE; idx++) {
+ if (ae->ae_state != ae_unused) arp_delete(ae);
+ ae++;
+ }
+
+ /*
+ * Free up the memory.
+ */
+
+ KFREE(ipi->arp_table);
+ ipi->arp_table = NULL;
+ ipi->arp_port = -1;
+}
+
+
+/* *********************************************************************
+ * _arp_enumerate(ipi,entrynum,ipaddr,hwaddr)
+ *
+ * Enumerate the ARP table. This is used by user-interface
+ * routines to display the current contents of the ARP table.
+ *
+ * Input parameters:
+ * ipi - IP information
+ * entrynum - entry index
+ * ipaddr - buffer to copy entry's IP address to
+ * hwaddr - buffer to copy entry's hardware address to
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int _arp_enumerate(ip_info_t *ipi,int entrynum,uint8_t *ipaddr,uint8_t *hwaddr)
+{
+ arpentry_t *ae;
+ int idx;
+
+ ae = ipi->arp_table;
+ for (idx = 0; idx < ARP_TABLE_SIZE; idx++) {
+ if (ae->ae_state != ae_unused) {
+ if (entrynum == 0) {
+ memcpy(ipaddr,ae->ae_ipaddr,IP_ADDR_LEN);
+ memcpy(hwaddr,ae->ae_ethaddr,ENET_ADDR_LEN);
+ return 0;
+ }
+ entrynum--;
+ }
+ ae++;
+ }
+
+ return -1;
+}
+
+
+/* *********************************************************************
+ * _arp_delete(ipi,ipaddr)
+ *
+ * Delete an ARP entry. This routine takes an IP address, looks
+ * up its ARP table entry, and removes it from the table.
+ *
+ * Input parameters:
+ * ipi - IP information
+ * ipaddr - IP address whose entry to delete
+ *
+ * Return value:
+ * 0 if entry was deleted
+ * <0 if entry was not found
+ ********************************************************************* */
+
+int _arp_delete(ip_info_t *ipi,uint8_t *ipaddr)
+{
+ arpentry_t *ae;
+
+ ae = arp_find_entry(ipi,ipaddr);
+
+ if (ae) {
+ arp_delete(ae);
+ return 0;
+ }
+ return -1;
+}
diff --git a/cfe/cfe/net/net_dhcp.c b/cfe/cfe/net/net_dhcp.c
new file mode 100644
index 0000000..84a39e6
--- /dev/null
+++ b/cfe/cfe/net/net_dhcp.c
@@ -0,0 +1,869 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * DHCP Client File: net_dhcp.c
+ *
+ * This module contains a DHCP client.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "env_subr.h"
+
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_ioctl.h"
+#include "cfe_timer.h"
+#include "cfe_error.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+
+#include "cfe.h"
+
+#include "net_api.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+
+#define UDP_PORT_BOOTPS 67
+#define UDP_PORT_BOOTPC 68
+
+#define DHCP_REQ_TIMEOUT (1*CFE_HZ)
+#define DHCP_NUM_RETRIES 8
+
+#define DHCP_OP_BOOTREQUEST 1
+#define DHCP_OP_BOOTREPLY 2
+
+#define DHCP_HWTYPE_ETHERNET 1
+
+#define DHCP_TAG_FUNCTION 53
+#define DHCP_FUNCTION_DISCOVER 1
+#define DHCP_FUNCTION_OFFER 2
+#define DHCP_FUNCTION_REQUEST 3
+#define DHCP_FUNCTION_ACK 5
+
+#define DHCP_TAG_NETMASK 1
+#define DHCP_TAG_DOMAINNAME 0x0F
+#define DHCP_TAG_GATEWAY 0x03
+#define DHCP_TAG_NAMESERVER 0x06
+#define DHCP_TAG_SWAPSERVER 0x10
+#define DHCP_TAG_ROOTPATH 0x11
+#define DHCP_TAG_EXTENSIONS 0x12
+#define DHCP_TAG_SERVERIDENT 54
+#define DHCP_TAG_PARAMLIST 55
+#define DHCP_TAG_CLIENTID 61
+#define DHCP_TAG_CLASSID 60
+#define DHCP_TAG_REQADDR 50
+#define DHCP_TAG_LEASE_TIME 51
+#define DHCP_TAG_SCRIPT 130 /* CFE extended option */
+#define DHCP_TAG_OPTIONS 131 /* CFE extended option */
+
+#define DHCP_TAG_END 0xFF
+
+#define DHCP_MAGIC_NUMBER 0x63825363
+
+/*#define _DEBUG_*/
+
+
+/* *********************************************************************
+ * dhcp_set_envvars(reply)
+ *
+ * Using the supplied DHCP reply data, set environment variables
+ * to contain data from the reply.
+ *
+ * Input parameters:
+ * reply - dhcp reply
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void dhcp_set_envvars(dhcpreply_t *reply)
+{
+ char buffer[50];
+
+ env_delenv("BOOT_SERVER");
+ env_delenv("BOOT_FILE");
+ env_delenv("BOOT_SCRIPT");
+ env_delenv("BOOT_OPTIONS");
+
+ if (reply->dr_bootserver[0] | reply->dr_bootserver[1] |
+ reply->dr_bootserver[2] | reply->dr_bootserver[3]) {
+ sprintf(buffer,"%I",reply->dr_bootserver);
+ env_setenv("BOOT_SERVER",buffer,ENV_FLG_BUILTIN);
+ }
+
+ if (reply->dr_bootfile && reply->dr_bootfile[0]) {
+ env_setenv("BOOT_FILE",reply->dr_bootfile,ENV_FLG_BUILTIN);
+ }
+
+ if (reply->dr_script && reply->dr_script[0]) {
+ env_setenv("BOOT_SCRIPT",reply->dr_script,ENV_FLG_BUILTIN);
+ }
+
+ if (reply->dr_options && reply->dr_options[0]) {
+ env_setenv("BOOT_OPTIONS",reply->dr_options,ENV_FLG_BUILTIN);
+ }
+}
+
+/* *********************************************************************
+ * dhcp_dumptag(tag,len,buf)
+ *
+ * Dump out information from a DHCP tag
+ *
+ * Input parameters:
+ * tag - tag ID
+ * len - length of data
+ * buf - data
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+#ifdef _DEBUG_
+static void dhcp_dumptag(uint8_t tag,uint8_t len,uint8_t *buf)
+{
+ unsigned int idx;
+
+ xprintf("DHCP: ");
+
+ switch (tag) {
+ case DHCP_TAG_FUNCTION:
+ xprintf("DHCP Function: %d\n",buf[0]);
+ break;
+ case DHCP_TAG_LEASE_TIME:
+ idx = (((unsigned int) buf[0]) << 24) |
+ (((unsigned int) buf[1]) << 16) |
+ (((unsigned int) buf[2]) << 8) |
+ (((unsigned int) buf[3]) << 0);
+ xprintf("Lease Time: %d seconds\n",idx);
+ break;
+ case DHCP_TAG_SERVERIDENT:
+ xprintf("DHCP Server ID: %d.%d.%d.%d\n",
+ buf[0],buf[1],buf[2],buf[3]);
+ break;
+ case DHCP_TAG_NETMASK:
+ xprintf("Netmask: %d.%d.%d.%d\n",buf[0],buf[1],buf[2],buf[3]);
+ break;
+ case DHCP_TAG_DOMAINNAME:
+ buf[len] = 0;
+ xprintf("Domain: %s\n",buf);
+ break;
+ case DHCP_TAG_GATEWAY:
+ xprintf("Gateway: %d.%d.%d.%d\n",buf[0],buf[1],buf[2],buf[3]);
+ break;
+ case DHCP_TAG_NAMESERVER:
+ xprintf("Nameserver: %d.%d.%d.%d\n",buf[0],buf[1],buf[2],buf[3]);
+ break;
+ case DHCP_TAG_SWAPSERVER:
+ buf[len] = 0;
+ xprintf("Swapserver: %s\n",buf);
+ break;
+ case DHCP_TAG_ROOTPATH:
+ buf[len] = 0;
+ xprintf("Rootpath: %s\n",buf);
+ break;
+ case DHCP_TAG_SCRIPT:
+ buf[len] = 0;
+ xprintf("CFE Script: %s\n",buf);
+ break;
+ case DHCP_TAG_OPTIONS:
+ buf[len] = 0;
+ xprintf("CFE Boot Options: %s\n",buf);
+ break;
+ default:
+ xprintf("Tag %d len %d [",tag,len);
+ for (idx = 0; idx < len; idx++) {
+ if ((buf[idx] >= 32) && (buf[idx] < 127)) xprintf("%c",buf[idx]);
+ }
+ xprintf("]\n");
+ break;
+
+ }
+}
+#endif
+
+/* *********************************************************************
+ * dhcp_free_reply(reply)
+ *
+ * Free memory associated with a DHCP reply.
+ *
+ * Input parameters:
+ * reply - pointer to DHCP reply
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void dhcp_free_reply(dhcpreply_t *reply)
+{
+ if (reply->dr_hostname) KFREE(reply->dr_hostname);
+ if (reply->dr_domainname) KFREE(reply->dr_domainname);
+ if (reply->dr_bootfile) KFREE(reply->dr_bootfile);
+ if (reply->dr_rootpath) KFREE(reply->dr_rootpath);
+ if (reply->dr_swapserver) KFREE(reply->dr_swapserver);
+ if (reply->dr_script) KFREE(reply->dr_script);
+ if (reply->dr_options) KFREE(reply->dr_options);
+ KFREE(reply);
+}
+
+/* *********************************************************************
+ * dhcp_build_discover()
+ *
+ * Build a DHCP DISCOVER packet
+ *
+ * Input parameters:
+ * hwaddr - our hardware address
+ * idptr - pointer to int to receive the DHCP packet ID
+ * serveraddr - pointer to server address (REQUEST) or
+ * NULL (DISCOVER)
+ * ebufptr - receives pointer to ebuf
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+static int dhcp_build_discover(uint8_t *hwaddr,
+ uint32_t id,
+ ebuf_t **ebufptr)
+{
+ uint8_t ipaddr[IP_ADDR_LEN];
+ ebuf_t *buf;
+ uint8_t junk[128];
+
+ /*
+ * Get a buffer and fill it in.
+ */
+
+ ipaddr[0] = 0; ipaddr[1] = 0; ipaddr[2] = 0; ipaddr[3] = 0;
+ memset(junk,0,sizeof(junk));
+
+ buf = udp_alloc();
+
+ if (buf == NULL) {
+ return CFE_ERR_NOMEM;
+ }
+
+ memset(buf->eb_ptr,0,548);
+
+ ebuf_append_u8(buf,DHCP_OP_BOOTREQUEST);
+ ebuf_append_u8(buf,DHCP_HWTYPE_ETHERNET);
+ ebuf_append_u8(buf,ENET_ADDR_LEN);
+ ebuf_append_u8(buf,0); /* hops */
+ ebuf_append_u32_be(buf,id);
+ ebuf_append_u16_be(buf,0); /* sec since boot */
+ ebuf_append_u16_be(buf,0); /* flags */
+
+ ebuf_append_bytes(buf,ipaddr,IP_ADDR_LEN); /* ciaddr */
+ ebuf_append_bytes(buf,ipaddr,IP_ADDR_LEN); /* yiaddr */
+ ebuf_append_bytes(buf,ipaddr,IP_ADDR_LEN); /* siaddr */
+ ebuf_append_bytes(buf,ipaddr,IP_ADDR_LEN); /* giaddr */
+
+ ebuf_append_bytes(buf,hwaddr,ENET_ADDR_LEN); /* chaddr */
+ ebuf_append_bytes(buf,junk,10); /* rest of chaddr */
+ ebuf_append_bytes(buf,junk,64); /* sname */
+ ebuf_append_bytes(buf,junk,128); /* file */
+
+ ebuf_append_u32_be(buf,DHCP_MAGIC_NUMBER);
+
+ ebuf_append_u8(buf,DHCP_TAG_FUNCTION); /* function code */
+ ebuf_append_u8(buf,1);
+ ebuf_append_u8(buf,DHCP_FUNCTION_DISCOVER);
+
+ ebuf_append_u8(buf,DHCP_TAG_PARAMLIST);
+ ebuf_append_u8(buf,8); /* count of tags that follow */
+ ebuf_append_u8(buf,DHCP_TAG_NETMASK);
+ ebuf_append_u8(buf,DHCP_TAG_DOMAINNAME);
+ ebuf_append_u8(buf,DHCP_TAG_GATEWAY);
+ ebuf_append_u8(buf,DHCP_TAG_NAMESERVER);
+ ebuf_append_u8(buf,DHCP_TAG_SWAPSERVER);
+ ebuf_append_u8(buf,DHCP_TAG_ROOTPATH);
+ ebuf_append_u8(buf,DHCP_TAG_SCRIPT);
+ ebuf_append_u8(buf,DHCP_TAG_OPTIONS);
+
+
+ ebuf_append_u8(buf,DHCP_TAG_END); /* terminator */
+
+ /*
+ * Return the packet
+ */
+
+ *ebufptr = buf;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * dhcp_build_request()
+ *
+ * Build a DHCP DISCOVER or REQUEST packet
+ *
+ * Input parameters:
+ * hwaddr - our hardware address
+ * idptr - pointer to int to receive the DHCP packet ID
+ * serveraddr - pointer to server address (REQUEST) or
+ * NULL (DISCOVER)
+ * ebufptr - receives pointer to ebuf
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+static int dhcp_build_request(uint8_t *hwaddr,
+ uint32_t id,
+ uint8_t *serveraddr,
+ uint8_t *reqip,
+ ebuf_t **ebufptr)
+{
+ uint8_t ipaddr[IP_ADDR_LEN];
+ ebuf_t *buf;
+ uint8_t junk[128];
+
+ /*
+ * Get a buffer and fill it in.
+ */
+
+ ipaddr[0] = 0; ipaddr[1] = 0; ipaddr[2] = 0; ipaddr[3] = 0;
+ memset(junk,0,sizeof(junk));
+
+ buf = udp_alloc();
+
+ if (buf == NULL) {
+ return CFE_ERR_NOMEM;
+ }
+
+ memset(buf->eb_ptr,0,548);
+
+ ebuf_append_u8(buf,DHCP_OP_BOOTREQUEST);
+ ebuf_append_u8(buf,DHCP_HWTYPE_ETHERNET);
+ ebuf_append_u8(buf,ENET_ADDR_LEN);
+ ebuf_append_u8(buf,0); /* hops */
+ ebuf_append_u32_be(buf,id);
+ ebuf_append_u16_be(buf,0); /* sec since boot */
+ ebuf_append_u16_be(buf,0); /* flags */
+
+ ebuf_append_bytes(buf,ipaddr,IP_ADDR_LEN); /* ciaddr */
+ ebuf_append_bytes(buf,ipaddr,IP_ADDR_LEN); /* yiaddr */
+ ebuf_append_bytes(buf,ipaddr,IP_ADDR_LEN); /* siaddr */
+ ebuf_append_bytes(buf,ipaddr,IP_ADDR_LEN); /* giaddr */
+
+ ebuf_append_bytes(buf,hwaddr,ENET_ADDR_LEN); /* chaddr */
+ ebuf_append_bytes(buf,junk,10); /* rest of chaddr */
+
+ ebuf_append_bytes(buf,junk,64); /* sname */
+
+ ebuf_append_bytes(buf,junk,128); /* file */
+
+ ebuf_append_u32_be(buf,DHCP_MAGIC_NUMBER);
+
+ ebuf_append_u8(buf,DHCP_TAG_FUNCTION); /* function code */
+ ebuf_append_u8(buf,1);
+
+ ebuf_append_u8(buf,DHCP_FUNCTION_REQUEST);
+
+ ebuf_append_u8(buf,DHCP_TAG_REQADDR);
+ ebuf_append_u8(buf,IP_ADDR_LEN);
+ ebuf_append_bytes(buf,reqip,IP_ADDR_LEN);
+
+ ebuf_append_u8(buf,DHCP_TAG_SERVERIDENT); /* server ID */
+ ebuf_append_u8(buf,IP_ADDR_LEN);
+ ebuf_append_bytes(buf,serveraddr,IP_ADDR_LEN);
+
+ ebuf_append_u8(buf,DHCP_TAG_CLIENTID); /* client ID */
+ ebuf_append_u8(buf,7);
+ ebuf_append_u8(buf,1);
+ ebuf_append_bytes(buf,hwaddr,ENET_ADDR_LEN);
+
+ ebuf_append_u8(buf,DHCP_TAG_PARAMLIST);
+ ebuf_append_u8(buf,8); /* count of tags that follow */
+ ebuf_append_u8(buf,DHCP_TAG_NETMASK);
+ ebuf_append_u8(buf,DHCP_TAG_DOMAINNAME);
+ ebuf_append_u8(buf,DHCP_TAG_GATEWAY);
+ ebuf_append_u8(buf,DHCP_TAG_NAMESERVER);
+ ebuf_append_u8(buf,DHCP_TAG_SWAPSERVER);
+ ebuf_append_u8(buf,DHCP_TAG_ROOTPATH);
+ ebuf_append_u8(buf,DHCP_TAG_SCRIPT);
+ ebuf_append_u8(buf,DHCP_TAG_OPTIONS);
+
+
+ ebuf_append_u8(buf,DHCP_TAG_END); /* terminator */
+
+ /*
+ * Return the packet
+ */
+
+ *ebufptr = buf;
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * dhcp_wait_reply(s,id,reply,serveraddr)
+ *
+ * Wait for a reply from the DHCP server
+ *
+ * Input parameters:
+ * s - socket
+ * id - ID of request we sent
+ * reply - structure to store results in
+ * expfcode - expected DHCP_FUNCTION tag value
+ *
+ * Return value:
+ * 0 if ok (reply found)
+ * else error
+ ********************************************************************* */
+
+static int dhcp_wait_reply(int s,uint32_t id,dhcpreply_t *reply,int expfcode)
+{
+ uint32_t tmpd;
+ uint8_t tmpb;
+ int64_t timer;
+ int nres = 0;
+ uint8_t ciaddr[IP_ADDR_LEN];
+ uint8_t yiaddr[IP_ADDR_LEN];
+ uint8_t siaddr[IP_ADDR_LEN];
+ uint8_t giaddr[IP_ADDR_LEN];
+ uint8_t junk[128];
+ char *hostname;
+ char *bootfile;
+ ebuf_t *buf;
+ int fcode = -1;
+
+ /*
+ * Set a timer for the response
+ */
+
+ TIMER_SET(timer,DHCP_REQ_TIMEOUT);
+
+ /*
+ * Start waiting...
+ */
+
+ while (!TIMER_EXPIRED(timer)) {
+ POLL();
+
+ buf = udp_recv(s);
+ if (!buf) continue;
+
+ ebuf_get_u8(buf,tmpb);
+ if (tmpb != DHCP_OP_BOOTREPLY) {
+ goto drop;
+ }
+
+ ebuf_get_u8(buf,tmpb);
+ if (tmpb != DHCP_HWTYPE_ETHERNET) {
+ goto drop;
+ }
+
+ ebuf_get_u8(buf,tmpb);
+ if (tmpb != ENET_ADDR_LEN) {
+ goto drop;
+ }
+
+ ebuf_skip(buf,1); /* hops */
+
+ ebuf_get_u32_be(buf,tmpd); /* check ID */
+ if (tmpd != id) {
+ goto drop;
+ }
+
+ ebuf_skip(buf,2); /* seconds since boot */
+ ebuf_skip(buf,2); /* flags */
+
+ ebuf_get_bytes(buf,ciaddr,IP_ADDR_LEN);
+ ebuf_get_bytes(buf,yiaddr,IP_ADDR_LEN);
+ ebuf_get_bytes(buf,siaddr,IP_ADDR_LEN);
+ ebuf_get_bytes(buf,giaddr,IP_ADDR_LEN);
+
+ ebuf_skip(buf,16); /* hardware address */
+ hostname = ebuf_ptr(buf);
+ ebuf_skip(buf,64);
+ bootfile = ebuf_ptr(buf);
+
+ ebuf_skip(buf,128);
+
+#ifdef _DEBUG_
+ xprintf("Client IP: %d.%d.%d.%d\n",ciaddr[0],ciaddr[1],ciaddr[2],ciaddr[3]);
+ xprintf("Your IP: %d.%d.%d.%d\n",yiaddr[0],yiaddr[1],yiaddr[2],yiaddr[3]);
+ xprintf("Server IP: %d.%d.%d.%d\n",siaddr[0],siaddr[1],siaddr[2],siaddr[3]);
+ xprintf("Gateway IP: %d.%d.%d.%d\n",giaddr[0],giaddr[1],giaddr[2],giaddr[3]);
+ xprintf("hostname: %s\n",hostname);
+ xprintf("boot file: %s\n",bootfile);
+#endif
+
+ memcpy(reply->dr_ipaddr,yiaddr,IP_ADDR_LEN);
+ memcpy(reply->dr_gateway,giaddr,IP_ADDR_LEN);
+ memcpy(reply->dr_bootserver,siaddr,IP_ADDR_LEN);
+ if (*hostname) reply->dr_hostname = strdup(hostname);
+ if (*bootfile) reply->dr_bootfile = strdup(bootfile);
+
+ /*
+ * Test for options - look for magic number
+ */
+
+ ebuf_get_u32_be(buf,tmpd);
+
+ memcpy(reply->dr_dhcpserver,buf->eb_usrptr,IP_ADDR_LEN);
+
+ if (tmpd == DHCP_MAGIC_NUMBER) {
+ uint8_t tag;
+ uint8_t len;
+
+ while (buf->eb_length > 0) {
+ ebuf_get_u8(buf,tag);
+ if (tag == DHCP_TAG_END) break;
+ ebuf_get_u8(buf,len);
+ ebuf_get_bytes(buf,junk,len);
+
+#ifdef _DEBUG_
+ dhcp_dumptag(tag,len,junk);
+#endif
+
+ switch (tag) {
+ case DHCP_TAG_FUNCTION:
+ fcode = (uint8_t) junk[0];
+ break;
+ case DHCP_TAG_NETMASK:
+ memcpy(reply->dr_netmask,junk,IP_ADDR_LEN);
+ break;
+ case DHCP_TAG_GATEWAY:
+ memcpy(reply->dr_gateway,junk,IP_ADDR_LEN);
+ break;
+ case DHCP_TAG_NAMESERVER:
+ memcpy(reply->dr_nameserver,junk,IP_ADDR_LEN);
+ break;
+ case DHCP_TAG_DOMAINNAME:
+ junk[len] = 0;
+ if (len) reply->dr_domainname = strdup(junk);
+ break;
+ case DHCP_TAG_SWAPSERVER:
+ junk[len] = 0;
+ if (len) reply->dr_swapserver = strdup(junk);
+ break;
+ case DHCP_TAG_SERVERIDENT:
+ if (len == IP_ADDR_LEN) {
+ memcpy(reply->dr_dhcpserver,junk,len);
+ }
+ break;
+ case DHCP_TAG_ROOTPATH:
+ junk[len] = 0;
+ if (len) reply->dr_rootpath = strdup(junk);
+ break;
+ case DHCP_TAG_SCRIPT:
+ junk[len] = 0;
+ if (len) reply->dr_script = strdup(junk);
+ break;
+ case DHCP_TAG_OPTIONS:
+ junk[len] = 0;
+ if (len) reply->dr_options = strdup(junk);
+ break;
+ }
+ }
+ }
+
+ if (fcode != expfcode) {
+ goto drop;
+ }
+
+ udp_free(buf);
+ nres++;
+ break;
+
+ drop:
+ udp_free(buf);
+ }
+
+ if (nres > 0) return 0;
+ else return CFE_ERR_TIMEOUT;
+}
+
+
+/* *********************************************************************
+ * dhcp_do_dhcpdiscover(s,hwaddr,reply)
+ *
+ * Request an IP address from the DHCP server. On success, the
+ * dhcpreply_t structure will be filled in
+ *
+ * Input parameters:
+ * s - udp socket
+ * hwaddr - our hardware address
+ * reply - pointer to reply buffer.
+ *
+ * Return value:
+ * 0 if a response was received
+ * else error code
+ ********************************************************************* */
+
+static int dhcp_do_dhcpdiscover(int s,uint8_t *hwaddr,dhcpreply_t *reply)
+{
+ ebuf_t *buf;
+ uint32_t id;
+ uint8_t ipaddr[IP_ADDR_LEN];
+ int res;
+
+ /*
+ * Packet ID is the current time
+ */
+
+ id = (uint32_t)cfe_ticks;
+
+ /*
+ * Build the DISCOVER request
+ */
+
+ res = dhcp_build_discover(hwaddr,id,&buf);
+ if (res != 0) return res;
+
+ /*
+ * Send the packet to the IP broadcast (255.255.255.255)
+ */
+
+ ipaddr[0] = 0xFF; ipaddr[1] = 0xFF; ipaddr[2] = 0xFF; ipaddr[3] = 0xFF;
+ udp_send(s,buf,ipaddr);
+
+ /*
+ * Wait for a reply
+ */
+
+ res = dhcp_wait_reply(s,id,reply,DHCP_FUNCTION_OFFER);
+
+ return res;
+}
+
+
+/* *********************************************************************
+ * dhcp_do_dhcprequest(s,hwaddr,reply,discover_reply)
+ *
+ * Request an IP address from the DHCP server. On success, the
+ * dhcpreply_t structure will be filled in
+ *
+ * Input parameters:
+ * s - udp socket
+ * hwaddr - our hardware address
+ * reply - pointer to reply buffer.
+ * discover_reply - pointer to previously received DISCOVER data
+ *
+ * Return value:
+ * 0 if a response was received
+ * else error code
+ ********************************************************************* */
+
+static int dhcp_do_dhcprequest(int s,uint8_t *hwaddr,
+ dhcpreply_t *reply,
+ dhcpreply_t *discover_reply)
+{
+ ebuf_t *buf;
+ uint32_t id;
+ uint8_t ipaddr[IP_ADDR_LEN];
+ int res;
+
+ /*
+ * Packet ID is the current time
+ */
+
+ id = (uint32_t)cfe_ticks;
+
+ /*
+ * Build the DHCP REQUEST request
+ */
+
+ res = dhcp_build_request(hwaddr,
+ id,
+ discover_reply->dr_dhcpserver,
+ discover_reply->dr_ipaddr,
+ &buf);
+
+ if (res != 0) return res;
+
+ /*
+ * Send the packet to the IP broadcast (255.255.255.255)
+ */
+
+ ipaddr[0] = 0xFF; ipaddr[1] = 0xFF; ipaddr[2] = 0xFF; ipaddr[3] = 0xFF;
+ udp_send(s,buf,ipaddr);
+
+ /*
+ * Wait for a reply
+ */
+
+ res = dhcp_wait_reply(s,id,reply,DHCP_FUNCTION_ACK);
+
+ return res;
+}
+
+
+/* *********************************************************************
+ * dhcp_bootrequest(reply)
+ *
+ * Request an IP address from the DHCP server. On success, the
+ * dhcpreply_t structure will be allocated.
+ *
+ * Input parameters:
+ * reply - pointer to pointer to reply.
+ *
+ * Return value:
+ * 0 if no responses received
+ * >0 for some responses received
+ * else error code
+ ********************************************************************* */
+
+int dhcp_bootrequest(dhcpreply_t **rep)
+{
+ uint8_t *hwaddr;
+ int s;
+ dhcpreply_t *discover_reply;
+ dhcpreply_t *request_reply;
+ int nres = 0;
+ int retries;
+ uint32_t id;
+
+ id = (uint32_t) cfe_ticks;
+
+ /*
+ * Start with empty reply buffers. Since we use a portion of the
+ * discover reply in the request, we'll keep two of them.
+ */
+
+ discover_reply = KMALLOC(sizeof(dhcpreply_t),0);
+ if (discover_reply == NULL) {
+ return CFE_ERR_NOMEM;
+ }
+ memset(discover_reply,0,sizeof(dhcpreply_t));
+
+ request_reply = KMALLOC(sizeof(dhcpreply_t),0);
+ if (request_reply == NULL) {
+ KFREE(discover_reply);
+ return CFE_ERR_NOMEM;
+ }
+ memset(request_reply,0,sizeof(dhcpreply_t));
+
+
+ /*
+ * Get our hw addr
+ */
+
+ hwaddr = net_getparam(NET_HWADDR);
+ if (!hwaddr) {
+ KFREE(discover_reply);
+ KFREE(request_reply);
+ return CFE_ERR_NETDOWN;
+ }
+
+ /*
+ * Open UDP port
+ */
+
+ s = udp_socket(UDP_PORT_BOOTPS);
+ if (s < 0) {
+ KFREE(discover_reply);
+ KFREE(request_reply);
+ return CFE_ERR_NOHANDLES;
+ }
+
+ udp_bind(s,UDP_PORT_BOOTPC);
+
+ /*
+ * Do the boot request. Start by sending the OFFER message
+ */
+
+ nres = CFE_ERR_TIMEOUT;
+ for (retries = 0; retries < DHCP_NUM_RETRIES; retries++) {
+ nres = dhcp_do_dhcpdiscover(s,hwaddr,discover_reply);
+ if (nres == 0) break;
+ if (nres == CFE_ERR_TIMEOUT) continue;
+ break;
+ }
+
+ /*
+ * If someone sent us a response, send the REQUEST message
+ * to get a lease.
+ */
+
+ if (nres == 0) {
+
+ /*
+ * Now, send the REQUEST message and get a response.
+ */
+
+ for (retries = 0; retries < DHCP_NUM_RETRIES; retries++) {
+ nres = dhcp_do_dhcprequest(s,hwaddr,
+ request_reply,
+ discover_reply);
+ if (nres == 0) break;
+ if (nres == CFE_ERR_TIMEOUT) continue;
+ break;
+ }
+ }
+
+ /*
+ * All done with the discover reply.
+ */
+
+ dhcp_free_reply(discover_reply);
+
+ /*
+ * All done with UDP
+ */
+
+ udp_close(s);
+
+ /*
+ * Return the reply info.
+ */
+
+ if (nres == 0) {
+ *rep = request_reply;
+ }
+ else {
+ *rep = NULL;
+ dhcp_free_reply(request_reply);
+ }
+
+ return nres;
+}
diff --git a/cfe/cfe/net/net_dns.c b/cfe/cfe/net/net_dns.c
new file mode 100755
index 0000000..89b50b1
--- /dev/null
+++ b/cfe/cfe/net/net_dns.c
@@ -0,0 +1,354 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Domain Name System Resolver File: net_dns.c
+ *
+ * This module provides minimal support for looking up IP addresses
+ * from DNS name servers (RFCxxxx)
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_timer.h"
+#include "cfe_error.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+
+#include "cfe.h"
+
+#include "net_api.h"
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define ip_addriszero(a) (((a)[0]|(a)[1]|(a)[2]|(a)[3]) == 0)
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define UDP_PORT_DNS 53
+
+#define DNS_FLG_QUERY 0x0000
+#define DNS_FLG_RESPONSE 0x8000
+#define DNS_OPCODE_QUERY 0x0000
+#define DNS_FLG_AA 0x0400
+#define DNS_FLG_TC 0x0200
+#define DNS_FLG_RD 0x0100
+#define DNS_FLG_RA 0x0080
+#define DNS_RCODE_MASK 0x000F
+#define DNS_RCODE_OK 0x0000
+#define DNS_RCODE_NAMEERR 0x0003
+
+
+#define QTYPE_HOSTADDR 1
+#define QCLASS_INTERNET 1
+
+#define DNS_QUERY_TIMEOUT 1 /* seconds */
+#define DNS_RETRY_COUNT 8
+
+
+/* *********************************************************************
+ * dns_dolookup(s,hostname,ipaddr)
+ *
+ * Look up a host name and return its IP address.
+ *
+ * Input parameters:
+ * s - udp socket
+ * server - name server to query
+ * hostname - host name to find
+ * ipaddr - buffer to place IP address
+ *
+ * Return value:
+ * 0 if no responses found
+ * >0 to indicate number of response records (usually 1)
+ * else error code
+ ********************************************************************* */
+
+static int dns_dolookup(int s,uint8_t *server,char *hostname,uint8_t *ipaddr)
+{
+ ebuf_t *buf;
+ uint16_t id;
+ uint16_t tmp;
+ char *tok;
+ char *ptr;
+ int64_t timer;
+ int nres = 0;
+ uint16_t nqr,nar,nns,nxr;
+ uint8_t tmpb;
+ int expired;
+
+
+ /*
+ * Use the current time for our request ID
+ */
+
+ id = (uint16_t) cfe_ticks;
+
+ /*
+ * Get a buffer and fill it in.
+ */
+
+ buf = udp_alloc();
+
+ ebuf_append_u16_be(buf,id);
+ ebuf_append_u16_be(buf,(DNS_FLG_QUERY | DNS_OPCODE_QUERY | DNS_FLG_RD));
+ ebuf_append_u16_be(buf,1); /* one question */
+ ebuf_append_u16_be(buf,0); /* no answers */
+ ebuf_append_u16_be(buf,0); /* no server resource records */
+ ebuf_append_u16_be(buf,0); /* no additional records */
+
+ /*
+ * Chop up the hostname into pieces, basically replacing
+ * the dots with length indicators.
+ */
+
+ ptr = hostname;
+
+ while ((tok = strchr(ptr,'.'))) {
+ ebuf_append_u8(buf,(tok-ptr));
+ ebuf_append_bytes(buf,ptr,(tok-ptr));
+ ptr = tok + 1;
+ }
+
+ ebuf_append_u8(buf,strlen(ptr));
+ ebuf_append_bytes(buf,ptr,strlen(ptr));
+ ebuf_append_u8(buf,0);
+ ebuf_append_u16_be(buf,QTYPE_HOSTADDR);
+ ebuf_append_u16_be(buf,QCLASS_INTERNET);
+
+ /*
+ * Send the request to the name server
+ */
+
+ udp_send(s,buf,server);
+
+ /*
+ * Set a timer for the response
+ */
+
+ TIMER_SET(timer,DNS_QUERY_TIMEOUT*CFE_HZ);
+
+ /*
+ * Start waiting...
+ */
+
+ while (!(expired = TIMER_EXPIRED(timer))) {
+ POLL();
+
+ buf = udp_recv(s);
+ if (!buf) continue;
+
+ /* IDs must match */
+
+ ebuf_get_u16_be(buf,tmp);
+ if (id != tmp) goto drop;
+
+ /* It must be a response */
+
+ ebuf_get_u16_be(buf,tmp);
+
+ if ((tmp & DNS_FLG_RESPONSE) == 0) goto drop;
+
+ if ((tmp & DNS_RCODE_MASK) != DNS_RCODE_OK) {
+ udp_free(buf);
+ /* name error */
+ break;
+ }
+
+ ebuf_get_u16_be(buf,nqr);
+ ebuf_get_u16_be(buf,nar);
+ ebuf_get_u16_be(buf,nns);
+ ebuf_get_u16_be(buf,nxr);
+
+ if (nar == 0) {
+ goto drop;
+ }
+
+ while (nqr > 0) {
+ if (ebuf_length(buf) <= 0) {
+ goto drop;
+ }
+ for (;;) {
+ ebuf_get_u8(buf,tmpb);
+ if (tmpb == 0) break;
+ ebuf_skip(buf,tmpb);
+ if (ebuf_length(buf) <= 0) {
+ goto drop;
+ }
+ }
+ ebuf_skip(buf,2); /* skip QTYPE */
+ ebuf_skip(buf,2); /* skip QCLASS */
+ nqr--; /* next question record */
+ }
+
+ /*
+ * Loop through the answer records to find
+ * a HOSTADDR record. Ignore any other records
+ * we find.
+ */
+
+ while (nar > 0) {
+ uint16_t rname,rtype,rclass,dlen;
+
+ ebuf_get_u16_be(buf,rname); /* resource name */
+
+ ebuf_get_u16_be(buf,rtype); /* resource type */
+
+ ebuf_get_u16_be(buf,rclass); /* resource class */
+
+ ebuf_skip(buf,4); /* time to live */
+
+ ebuf_get_u16_be(buf,dlen); /* length of data */
+
+ if (rtype != QTYPE_HOSTADDR) {
+ ebuf_skip(buf,dlen);
+ nar--;
+ continue;
+ }
+ if (rclass != QCLASS_INTERNET) {
+ ebuf_skip(buf,dlen);
+ nar--;
+ continue;
+ }
+
+ if (dlen != IP_ADDR_LEN) {
+ ebuf_skip(buf,dlen);
+ nar--;
+ continue;
+ }
+
+ ebuf_get_bytes(buf,ipaddr,IP_ADDR_LEN);
+ break;
+ }
+
+ if (nar == 0) goto drop;
+
+ udp_free(buf);
+ nres++;
+ break;
+
+ drop:
+ udp_free(buf);
+ }
+
+ if (expired) return CFE_ERR_TIMEOUT;
+ if (nres == 0) return CFE_ERR_HOSTUNKNOWN;
+ return nres;
+}
+
+
+/* *********************************************************************
+ * dns_lookup(hostname,ipaddr)
+ *
+ * Look up a host name and return its IP address.
+ *
+ * Input parameters:
+ * hostname - host name to find
+ * ipaddr - buffer to place IP address
+ *
+ * Return value:
+ * 0 if no responses found
+ * >0 to indicate number of response records (usually 1)
+ * else error code
+ ********************************************************************* */
+
+int dns_lookup(char *hostname,uint8_t *ipaddr)
+{
+ int s;
+ int nres = 0;
+ int retries;
+ char temphostname[100];
+ uint8_t *server;
+ uint8_t *tok;
+
+ /*
+ * If it's a valid IP address, don't look it up.
+ */
+
+ if (parseipaddr(hostname,ipaddr) == 0) return 1;
+
+ /*
+ * Add default domain if no domain was specified
+ */
+
+ if (strchr(hostname,'.') == NULL) {
+ tok = net_getparam(NET_DOMAIN);
+ if (tok) {
+ xsprintf(temphostname,"%s.%s",hostname,tok);
+ hostname = temphostname;
+ }
+ }
+
+ /*
+ * Figure out who the name server is
+ */
+
+ server = net_getparam(NET_NAMESERVER);
+
+ if (!server) return CFE_ERR_NETDOWN;
+ if (ip_addriszero(server)) return CFE_ERR_NONAMESERVER;
+
+ /*
+ * Go do the name server lookup
+ */
+
+ s = udp_socket(UDP_PORT_DNS);
+ if (s < 0) return CFE_ERR_NOHANDLES;
+
+ for (retries = 0; retries < DNS_RETRY_COUNT; retries++) {
+ nres = dns_dolookup(s,server,hostname,ipaddr);
+ if (nres == CFE_ERR_TIMEOUT) continue;
+ if (nres >= 0) break;
+ }
+
+ udp_close(s);
+
+ return nres;
+
+}
diff --git a/cfe/cfe/net/net_ebuf.h b/cfe/cfe/net/net_ebuf.h
new file mode 100644
index 0000000..11d83c1
--- /dev/null
+++ b/cfe/cfe/net/net_ebuf.h
@@ -0,0 +1,165 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Network EBUF macros File: net_ebuf.h
+ *
+ * This file contains macros and function prototypes for
+ * messing with "ebuf" buffers. ebufs describe network
+ * packets. They're sort of like poor-man's mbufs :-)
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+
+#define ENET_MAX_PKT 1514
+#define ENET_CRC_SIZE 4
+#define ENET_ADDR_LEN 6
+#define ENET_DIX_HEADER 14
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+
+typedef struct ebuf_s {
+ queue_t eb_qblock; /* linkage */
+ unsigned int eb_length; /* length of area at eb_ptr */
+ unsigned int eb_status; /* rx/tx status */
+ int eb_port; /* eth port that owns buffer */
+ void *eb_device; /* underlying net device */
+ int eb_usrdata; /* user-defined stuff */
+ uint8_t *eb_usrptr; /* user-defined stuff */
+ uint8_t *eb_ptr; /* current ptr within pkt */
+ uint8_t eb_data[0x5F0]; /* data, must be > ENET_MAX_PKT */
+ /* and divisible by sizeof(uint) */
+} ebuf_t;
+
+/*
+ * Macros to initialize ebufs
+ */
+
+#define ebuf_init_rx(eb) (eb)->eb_ptr = (eb)->eb_data; \
+ (eb)->eb_length = 0; \
+ (eb)->eb_status = 0
+
+#define ebuf_init_tx(eb) (eb)->eb_ptr = (eb)->eb_data; \
+ (eb)->eb_length = 0; \
+ (eb)->eb_status = 0
+
+/*
+ * Macros to move the currens position within an ebuf
+ */
+
+#define ebuf_prepend(eb,amt) (eb)->eb_ptr -= amt; (eb)->eb_length += (amt)
+#define ebuf_adjust(eb,amt) (eb)->eb_ptr += (amt); (eb)->eb_length += (amt)
+#define ebuf_seek(eb,amt) (eb)->eb_ptr += (amt)
+
+#define ebuf_remlen(eb) ((eb)->eb_length)
+#define ebuf_length(eb) ((eb)->eb_length)
+#define ebuf_ptr(eb) ((eb)->eb_ptr)
+#define ebuf_setlength(eb,amt) (eb)->eb_length = (amt)
+
+/*
+ * ebuf_append_xxx macros - these macros add data to the
+ * end of a packet, adjusting the length
+ */
+
+#define ebuf_append_u8(eb,b) ((eb)->eb_ptr[(eb)->eb_length++]) = (b) ;
+#define ebuf_append_u16_be(eb,w) ebuf_append_u8(eb,((w) >> 8) & 0xFF) ; \
+ ebuf_append_u8(eb,((w) & 0xFF))
+
+#define ebuf_append_u32_be(eb,w) ebuf_append_u8(eb,((w) >> 24) & 0xFF) ; \
+ ebuf_append_u8(eb,((w) >> 16) & 0xFF) ; \
+ ebuf_append_u8(eb,((w) >> 8) & 0xFF) ; \
+ ebuf_append_u8(eb,((w) & 0xFF))
+
+#define ebuf_append_bytes(eb,b,l) memcpy(&((eb)->eb_ptr[(eb)->eb_length]),(b),(l)); \
+ (eb)->eb_length += (l)
+
+/*
+ * ebuf_put_xxx macros - these macros modify data in the middle
+ * of a packet, typically in an area already allocated with
+ * ebuf_adjust. The length is not updated, but the pointer is.
+ */
+
+#define ebuf_put_u8(eb,b) *((eb)->eb_ptr++) = (b)
+#define ebuf_put_u16_be(eb,w) ebuf_put_u8(eb,((w) >> 8) & 0xFF) ; \
+ ebuf_put_u8(eb,((w) & 0xFF))
+
+#define ebuf_put_u32_be(eb,w) ebuf_put_u8(eb,((w) >> 24) & 0xFF) ; \
+ ebuf_put_u8(eb,((w) >> 16) & 0xFF) ; \
+ ebuf_put_u8(eb,((w) >> 8) & 0xFF) ; \
+ ebuf_put_u8(eb,((w) & 0xFF))
+
+#define ebuf_put_bytes(eb,b,l) memcpy((buf)->eb_ptr,(b),(l)) ; (buf)->eb_ptr += (l)
+
+#define ebuf_srcaddr(eb) &((eb)->eb_data[6])
+#define ebuf_destaddr(eb) &((eb)->eb_data[0])
+
+/* return next byte from the ebuf, and advance pointer */
+
+#define ebuf_skip(eb,amt) (eb)->eb_length -= (amt); (eb)->eb_ptr += (amt)
+
+#define ebuf_get_u8(eb,v) (eb)->eb_length--; \
+ v = (*((eb)->eb_ptr++))
+
+/* return next u16 from the ebuf, big-endian */
+
+#define ebuf_get_u16_be(eb,v) (eb)->eb_ptr+=2; \
+ (eb)->eb_length-=2; \
+ v = ( ((uint16_t)*((eb)->eb_ptr-1)) | \
+ (((uint16_t)*((eb)->eb_ptr-2)) << 8) )
+
+/* return next u32 from the ebuf, big-endian */
+
+#define ebuf_get_u32_be(eb,v) (eb)->eb_ptr+=4; \
+ (eb)->eb_length-=4; \
+ v = ( ((uint32_t)*((eb)->eb_ptr-1)) | \
+ (((uint32_t)*((eb)->eb_ptr-2)) << 8) | \
+ (((uint32_t)*((eb)->eb_ptr-3)) << 16) | \
+ (((uint32_t)*((eb)->eb_ptr-4)) << 24) )
+
+#define ebuf_get_bytes(eb,b,l) memcpy((b),(buf)->eb_ptr,(l)) ; (eb)->eb_ptr += (l) ; (eb)->eb_length -= (l)
+
+
diff --git a/cfe/cfe/net/net_ether.c b/cfe/cfe/net/net_ether.c
new file mode 100644
index 0000000..0dec6e8
--- /dev/null
+++ b/cfe/cfe/net/net_ether.c
@@ -0,0 +1,705 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Ethernet Datalink File: net_ether.c
+ *
+ * This module provides a simple datalink (LLC1) interface
+ * capable of demultiplexing standard DIX-style Ethernet packets.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_ioctl.h"
+#include "cfe_error.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define ETH_MAX_PORTS 4
+#define ETH_MAX_BUFFERS 8
+
+/* *********************************************************************
+ * Types
+ ********************************************************************* */
+
+typedef struct ether_port_s {
+ int ep_dev;
+ uint8_t ep_proto[8];
+ int ep_ptype;
+ int ep_mtu;
+ int (*ep_rxcallback)(ebuf_t *buf,void *ref);
+ void *ep_ref;
+} ether_port_t;
+
+struct ether_info_s {
+ ether_port_t *eth_ports;
+ queue_t eth_freelist;
+ uint8_t eth_hwaddr[6];
+ int eth_devhandle;
+ ebuf_t *eth_bufpool;
+};
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+const uint8_t eth_broadcast[ENET_ADDR_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+
+
+/* *********************************************************************
+ * eth_open(eth,ptye,pdata,cb)
+ *
+ * Open an Ethernet portal.
+ *
+ * Input parameters:
+ * eth - ethernet context
+ * ptype - protocol type (ETH_PTYPE_xxx)
+ * pdata - protocol data (two bytes for DIX protocols)
+ * cb - callback for receive packets
+ *
+ * Return value:
+ * portal number
+ * or <0 if error occured
+ ********************************************************************* */
+
+int eth_open(ether_info_t *eth,int ptype,char *pdata,
+ int (*cb)(ebuf_t *buf,void *ref),void *ref)
+{
+ ether_port_t *p;
+ int portnum;
+
+ p = eth->eth_ports;
+
+ for (portnum = 0; portnum < ETH_MAX_PORTS; portnum++,p++) {
+ if (p->ep_rxcallback == NULL) break;
+ }
+
+ if (portnum == ETH_MAX_PORTS) {
+ return CFE_ERR_NOHANDLES; /* no ports left */
+ }
+
+ switch (ptype) {
+ case ETH_PTYPE_DIX:
+ p->ep_proto[0] = pdata[0];
+ p->ep_proto[1] = pdata[1];
+ p->ep_mtu = ENET_MAX_PKT - ENET_DIX_HEADER;
+ break;
+
+ case ETH_PTYPE_802SAP:
+ case ETH_PTYPE_802SNAP:
+ default:
+ /*
+ * we only support DIX etypes right now. If we ever want to support
+ * non-IP stacks (unlikely) this will need to change.
+ */
+ return CFE_ERR_UNSUPPORTED;
+ }
+
+ p->ep_ptype = ptype;
+ p->ep_rxcallback = cb;
+ p->ep_dev = eth->eth_devhandle;
+ p->ep_ref = ref;
+
+ return portnum;
+}
+
+
+/* *********************************************************************
+ * eth_close(eth,port)
+ *
+ * Close an Ethernet portal, freeing resources allocated to it.
+ *
+ * Input parameters:
+ * eth - ethernet context
+ * port - portal number
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void eth_close(ether_info_t *eth,int port)
+{
+ ether_port_t *p = &(eth->eth_ports[port]);
+
+ p->ep_ptype = 0;
+ p->ep_rxcallback = NULL;
+ p->ep_dev = 0;
+ memset(&(p->ep_proto[0]),0,sizeof(p->ep_proto));
+}
+
+
+/* *********************************************************************
+ * eth_findport(eth,buf)
+ *
+ * Locate the portal associated with a particular Ethernet packet.
+ * Parse the packet enough to determine if it's addressed
+ * correctly and to a valid protocol, and then look up the
+ * corresponding portal.
+ *
+ * Input parameters:
+ * eth - ethernet context
+ * buf - ethernet buffer to check
+ *
+ * Return value:
+ * eth_port_t structure or NULL if packet should be dropped
+ ********************************************************************* */
+
+static ether_port_t *eth_findport(ether_info_t *eth,ebuf_t *buf)
+{
+ int idx;
+ ether_port_t *p;
+
+ /*
+ * A few pre-flight checks: packets *from* multicast addresses
+ * are not allowed.
+ */
+
+ if (buf->eb_ptr[6] & 1) return NULL;
+
+ /*
+ * Packets smaller than minimum size are not allowed.
+ */
+
+ if (buf->eb_length < 60) return NULL;
+
+ /*
+ * Packets with bad status are not allowed
+ */
+
+ /* XXX if (buf->eb_status != 0) return NULL; */
+
+ /*
+ * Okay, scan the port list and find the matching portal.
+ */
+
+ for (idx = 0, p = eth->eth_ports; idx < ETH_MAX_PORTS; idx++,p++) {
+ if (!p->ep_rxcallback) continue; /* port not in use */
+
+ switch (p->ep_ptype) {
+ case ETH_PTYPE_DIX:
+ if ((p->ep_proto[0] == buf->eb_ptr[12]) &&
+ (p->ep_proto[1] == buf->eb_ptr[13])) {
+ ebuf_skip(buf,ENET_DIX_HEADER);
+ return p;
+ }
+ break;
+ case ETH_PTYPE_802SAP:
+ case ETH_PTYPE_802SNAP:
+ default:
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+/* *********************************************************************
+ * eth_poll(eth)
+ *
+ * Poll devices and process inbound packets. If new packets arrive,
+ * call the appropriate callback routine.
+ *
+ * Input parameters:
+ * eth - ethernet context
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void eth_poll(ether_info_t *eth)
+{
+ ebuf_t *buf;
+ ether_port_t *p;
+ int res;
+
+ /* XXX should this loop until all packets are processed? */
+
+ /*
+ * If no packets, just get out now
+ */
+
+ if (cfe_inpstat(eth->eth_devhandle) == 0) return;
+
+ /*
+ * get a packet from the free list
+ */
+
+ buf = (ebuf_t *) q_deqnext(&(eth->eth_freelist));
+ if (!buf) return;
+
+ /*
+ * Receive network data into the packet buffer
+ */
+
+ ebuf_init_rx(buf);
+ res = cfe_read(eth->eth_devhandle,buf->eb_ptr,ENET_MAX_PKT);
+
+ /*
+ * if receive error, get out now.
+ */
+
+ if (res <= 0) {
+ q_enqueue(&(eth->eth_freelist),(queue_t *) buf);
+ return;
+ }
+
+ /*
+ * init the rest of the fields in the ebuf
+ */
+
+ buf->eb_length = res;
+ buf->eb_status = 0;
+ buf->eb_device = eth;
+ buf->eb_usrdata = 0;
+
+ /*
+ * Look up the portal to receive the new packet
+ */
+
+ p = eth_findport(eth,buf);
+
+ /*
+ * Call the callback routine if we want to keep this
+ * buffer. Otherwise, drop it on the floor
+ */
+
+ if (p) {
+ buf->eb_port = p - eth->eth_ports;
+ res = (*(p->ep_rxcallback))(buf,p->ep_ref);
+ if (res == ETH_DROP) eth_free(buf);
+ }
+ else {
+ eth_free(buf);
+ }
+}
+
+
+/* *********************************************************************
+ * eth_gethwaddr(eth,hwaddr)
+ *
+ * Obtain the hardware address of the Ethernet interface.
+ *
+ * Input parameters:
+ * eth - ethernet context
+ * hwaddr - place to put hardware address - 6 bytes
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void eth_gethwaddr(ether_info_t *eth,uint8_t *hwaddr)
+{
+ memcpy(hwaddr,eth->eth_hwaddr,ENET_ADDR_LEN);
+}
+
+/* *********************************************************************
+ * eth_sethwaddr(eth,hwaddr)
+ *
+ * Set the hardware address of the Ethernet interface.
+ *
+ * Input parameters:
+ * eth - ethernet context
+ * hwaddr - new hardware address - 6 bytes
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void eth_sethwaddr(ether_info_t *eth,uint8_t *hwaddr)
+{
+ int retlen;
+
+ memcpy(eth->eth_hwaddr,hwaddr,ENET_ADDR_LEN);
+ cfe_ioctl(eth->eth_devhandle,IOCTL_ETHER_SETHWADDR,&(eth->eth_hwaddr[0]),
+ sizeof(eth->eth_hwaddr),&retlen,0);
+
+}
+
+
+
+/* *********************************************************************
+ * eth_setspeed(eth,speed)
+ *
+ * Set the speed of the Ethernet interface.
+ *
+ * Input parameters:
+ * eth - ethernet context
+ * speed - target speed (or auto for automatic)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+int eth_setspeed(ether_info_t *eth,int speed)
+{
+ int retlen;
+
+ return cfe_ioctl(eth->eth_devhandle,IOCTL_ETHER_SETSPEED,
+ (uint8_t *) &speed,sizeof(speed),&retlen,0);
+
+}
+
+/* *********************************************************************
+ * eth_setloopback(eth,loop)
+ *
+ * Configure loopback mode options for the Ethernet
+ *
+ * Input parameters:
+ * eth - ethernet context
+ * loop - loopback mode to set
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+int eth_setloopback(ether_info_t *eth,int loop)
+{
+ int retlen;
+
+ return cfe_ioctl(eth->eth_devhandle,IOCTL_ETHER_SETLOOPBACK,
+ (uint8_t *) &loop,sizeof(loop),&retlen,0);
+
+}
+
+/* *********************************************************************
+ * eth_getspeed(eth,speed)
+ *
+ * Get the current setting for the Ethernet speed (note that this
+ * is the speed we want to achieve, not the current speed)
+ *
+ * Input parameters:
+ * eth - ethernet context
+ * speed - pointer to int to receive speed
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+int eth_getspeed(ether_info_t *eth,int *speed)
+{
+ int retlen;
+
+ return cfe_ioctl(eth->eth_devhandle,IOCTL_ETHER_GETSPEED,
+ (uint8_t *) speed,sizeof(*speed),&retlen,0);
+
+}
+
+/* *********************************************************************
+ * eth_getloopback(eth,loop)
+ *
+ * Read the loopback state of the Ethernet interface
+ *
+ * Input parameters:
+ * eth - ethernet context
+ * loop - pointer to int to receive loopback state
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+int eth_getloopback(ether_info_t *eth,int *loop)
+{
+ int retlen;
+
+ return cfe_ioctl(eth->eth_devhandle,IOCTL_ETHER_GETLOOPBACK,
+ (uint8_t *) loop,sizeof(*loop),&retlen,0);
+
+}
+
+/* *********************************************************************
+ * eth_send(buf,dest)
+ *
+ * Transmit a packet.
+ *
+ * Input parameters:
+ * buf - ebuf structure describing packet
+ * dest - destination hardware address
+ *
+ * Return value:
+ * 0 - no error
+ * else error code
+ ********************************************************************* */
+
+int eth_send(ebuf_t *buf,uint8_t *dest)
+{
+ ether_info_t *eth = buf->eb_device;
+ ether_port_t *p = &(eth->eth_ports[buf->eb_port]);
+ int res;
+
+ switch (p->ep_ptype) {
+ case ETH_PTYPE_DIX:
+ ebuf_seek(buf,-ENET_DIX_HEADER);
+ ebuf_put_bytes(buf,dest,ENET_ADDR_LEN);
+ ebuf_put_bytes(buf,eth->eth_hwaddr,ENET_ADDR_LEN);
+ ebuf_put_bytes(buf,p->ep_proto,2);
+ /* adjust pointer and add in DIX header length */
+ ebuf_prepend(buf,ENET_DIX_HEADER);
+ break;
+ case ETH_PTYPE_802SAP:
+ case ETH_PTYPE_802SNAP:
+ default:
+ eth_free(buf); /* should not happen */
+ return CFE_ERR_UNSUPPORTED;
+ }
+
+ res = cfe_write(p->ep_dev,ebuf_ptr(buf),ebuf_length(buf));
+
+ /* XXX - should we free buffers here? */
+
+ return res;
+}
+
+/* *********************************************************************
+ * eth_alloc(eth,port)
+ *
+ * Allocate an Ethernet buffer. Ethernet buffers know what
+ * ports they are associated with, since we need to reserve
+ * space for the EThernet header, which might vary in size
+ * for DIX, 802, etc.
+ *
+ * Input parameters:
+ * eth - ethernet context
+ * port - portal ID
+ *
+ * Return value:
+ * ebuf, or NULL if no ebufs left
+ ********************************************************************* */
+
+ebuf_t *eth_alloc(ether_info_t *eth,int port)
+{
+ ebuf_t *buf;
+ ether_port_t *p = &(eth->eth_ports[port]);
+
+ buf = (ebuf_t *) q_deqnext(&(eth->eth_freelist));
+ if (buf == NULL) return NULL;
+
+ buf->eb_status = 0;
+ buf->eb_port = port;
+ buf->eb_device = eth;
+ ebuf_init_tx(buf);
+
+ switch (p->ep_ptype) {
+ case ETH_PTYPE_NONE:
+ break;
+ case ETH_PTYPE_DIX:
+ ebuf_seek(buf,ENET_DIX_HEADER);
+ break;
+ case ETH_PTYPE_802SAP:
+ case ETH_PTYPE_802SNAP:
+ default:
+ /* XXX Other ether types here */
+ break;
+ }
+
+ /*
+ * 'eb_ptr' points at new data, length is cleared.
+ * We will add the length back in at send time when the
+ * ethernet header is filled in.
+ */
+ buf->eb_length = 0;
+
+ return buf;
+}
+
+/* *********************************************************************
+ * eth_free(buf)
+ *
+ * Free an ebuf.
+ *
+ * Input parameters:
+ * buf - ebuf to free
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void eth_free(ebuf_t *buf)
+{
+ ether_info_t *eth = buf->eb_device;
+
+ q_enqueue(&(eth->eth_freelist),(queue_t *) buf);
+}
+
+
+/* *********************************************************************
+ * eth_getmtu(eth,port)
+ *
+ * Return the mtu of the specified Ethernet port. The mtu
+ * is the maximum number of bytes you can put in the buffer,
+ * excluding the Ethernet header.
+ *
+ * Input parameters:
+ * eth - ethernet context
+ * port - portal ID
+ *
+ * Return value:
+ * number of bytes
+ ********************************************************************* */
+
+
+int eth_getmtu(ether_info_t *eth,int port)
+{
+ ether_port_t *p = &(eth->eth_ports[port]);
+
+ return p->ep_mtu;
+}
+
+
+/* *********************************************************************
+ * eth_init(devname)
+ *
+ * Create an Ethernet context for a particular Ethernet device.
+ *
+ * Input parameters:
+ * devname - device name for underlying Ethernet driver
+ *
+ * Return value:
+ * ethernet context, or NULL of it could not be created.
+ ********************************************************************* */
+
+ether_info_t *eth_init(char *devname)
+{
+ int idx;
+ ebuf_t *buf;
+ ether_info_t *eth;
+ int devhandle;
+ int retlen;
+
+ /*
+ * Open the device driver
+ */
+
+ devhandle = cfe_open(devname);
+ if (devhandle < 0) return NULL;
+
+ eth = KMALLOC(sizeof(ether_info_t),0);
+ if (!eth) {
+ cfe_close(devhandle);
+ return NULL;
+ }
+
+ memset(eth,0,sizeof(ether_info_t));
+
+ /*
+ * Obtain hardware address
+ */
+
+ cfe_ioctl(devhandle,IOCTL_ETHER_GETHWADDR,&(eth->eth_hwaddr[0]),
+ sizeof(eth->eth_hwaddr),&retlen,0);
+
+ /*
+ * Allocate portal table
+ */
+
+ eth->eth_ports = KMALLOC(ETH_MAX_PORTS*sizeof(ether_port_t),0);
+ if (!eth->eth_ports) {
+ cfe_close(devhandle);
+ KFREE(eth);
+ return NULL;
+ }
+
+ memset(eth->eth_ports,0,ETH_MAX_PORTS*sizeof(ether_port_t));
+
+ /*
+ * Allocate buffer pool
+ */
+
+ eth->eth_bufpool = (ebuf_t *) KMALLOC(sizeof(ebuf_t)*ETH_MAX_BUFFERS,0);
+ if (!eth->eth_bufpool) {
+ cfe_close(devhandle);
+ KFREE(eth->eth_ports);
+ KFREE(eth);
+ return NULL;
+ }
+
+ /*
+ * Chain buffers onto the free list
+ */
+
+ q_init(&(eth->eth_freelist));
+ buf = eth->eth_bufpool;
+ for (idx = 0; idx < ETH_MAX_BUFFERS; idx++) {
+ q_enqueue(&(eth->eth_freelist),(queue_t *) buf);
+ buf++;
+ }
+
+ /*
+ * Remember the device handle
+ */
+
+ eth->eth_devhandle = devhandle;
+
+ return eth;
+}
+
+
+/* *********************************************************************
+ * eth_uninit(eth)
+ *
+ * Close and free up an Ethernet context
+ *
+ * Input parameters:
+ * eth - ethernet context
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void eth_uninit(ether_info_t *eth)
+{
+ cfe_close(eth->eth_devhandle);
+ KFREE(eth->eth_bufpool);
+ KFREE(eth->eth_ports);
+ KFREE(eth);
+}
+
+
diff --git a/cfe/cfe/net/net_ether.h b/cfe/cfe/net/net_ether.h
new file mode 100644
index 0000000..a94130b
--- /dev/null
+++ b/cfe/cfe/net/net_ether.h
@@ -0,0 +1,89 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Ethernet protocol demux defns File: net_ether.h
+ *
+ * constants and prototypes for the Ethernet datalink
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define ETH_PTYPE_NONE 0
+#define ETH_PTYPE_DIX 1
+#define ETH_PTYPE_802SAP 2
+#define ETH_PTYPE_802SNAP 3
+
+#define ETH_KEEP 1
+#define ETH_DROP 0
+
+/* *********************************************************************
+ * types
+ ********************************************************************* */
+
+typedef struct ether_info_s ether_info_t;
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+int eth_open(ether_info_t *eth,int ptype,char *pdata,int (*cb)(ebuf_t *buf,void *ref),void *ref);
+void eth_close(ether_info_t *eth,int port);
+void eth_poll(ether_info_t *eth);
+int eth_send(ebuf_t *buf,uint8_t *dest);
+ebuf_t *eth_alloc(ether_info_t *eth,int port);
+void eth_free(ebuf_t *buf);
+ether_info_t *eth_init(char *devname);
+void eth_uninit(ether_info_t *eth);
+int eth_getmtu(ether_info_t *,int port);
+void eth_gethwaddr(ether_info_t *,uint8_t *hwaddr);
+void eth_sethwaddr(ether_info_t *,uint8_t *hwaddr);
+int eth_getspeed(ether_info_t *,int *speed);
+int eth_setspeed(ether_info_t *,int speed);
+int eth_getloopback(ether_info_t *,int *loop);
+int eth_setloopback(ether_info_t *,int loop);
+extern const uint8_t eth_broadcast[ENET_ADDR_LEN];
+
+
+
diff --git a/cfe/cfe/net/net_icmp.c b/cfe/cfe/net/net_icmp.c
new file mode 100644
index 0000000..e98bc87
--- /dev/null
+++ b/cfe/cfe/net/net_icmp.c
@@ -0,0 +1,312 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * ICMP Protocol File: net_icmp.c
+ *
+ * This module implements portions of the ICMP protocol. Note
+ * that it is not a complete implementation, just enough to
+ * generate and respond to ICMP echo requests.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_timer.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+
+#include "net_ip.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define ICMP_CODE_ECHO 0
+#define ICMP_TYPE_ECHOREPLY 0
+#define ICMP_TYPE_ECHOREQ 8
+
+#define ICMPMSG(type,code) (((type)<<8)|(code))
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+struct icmp_info_s {
+ ip_info_t *icmp_ipinfo;
+ queue_t icmp_echoreplies;
+ int icmp_maxreplies;
+};
+
+/* *********************************************************************
+ * ICMP_RX_CALLBACK(ref,buf,dst,src)
+ *
+ * This routine is called by the IP layer when we receive
+ * ICMP protocol messages.
+ *
+ * Input parameters:
+ * ref - reference data (an icmp_info_t)
+ * buf - the ebuf containing the buffer
+ * dst - destination IP address (us, usually)
+ * src - source IP address
+ *
+ * Return value:
+ * ETH_KEEP to keep packet, ETH_DROP to cause packet to be freed
+ ********************************************************************* */
+
+static int icmp_rx_callback(void *ref,ebuf_t *buf,uint8_t *dst,uint8_t *src)
+{
+ icmp_info_t *icmp = (icmp_info_t *)ref;
+ ip_info_t *ipi = icmp->icmp_ipinfo;
+ uint16_t imsg;
+ uint16_t cksum;
+ ebuf_t *txbuf;
+ uint8_t *icmphdr;
+ int res;
+
+ imsg = ICMPMSG(buf->eb_ptr[0],buf->eb_ptr[1]);
+
+ res = ETH_DROP; /* assume we're dropping the pkt */
+
+ switch (imsg) {
+ case ICMPMSG(ICMP_TYPE_ECHOREQ,ICMP_CODE_ECHO):
+ txbuf = _ip_alloc(ipi);
+ if (txbuf) {
+ /* Construct reply from the original packet. */
+ icmphdr = txbuf->eb_ptr;
+ ebuf_append_bytes(txbuf,buf->eb_ptr,buf->eb_length);
+ icmphdr[0] = ICMP_TYPE_ECHOREPLY;
+ icmphdr[1] = ICMP_CODE_ECHO;
+ icmphdr[2] = 0; icmphdr[3] = 0;
+ cksum = ~ip_chksum(0,icmphdr,ebuf_length(txbuf));
+ icmphdr[2] = (cksum >> 8) & 0xFF;
+ icmphdr[3] = (cksum & 0xFF);
+ if (_ip_send(ipi,txbuf,src,IPPROTO_ICMP) < 0) {
+ _ip_free(ipi,txbuf);
+ }
+ }
+ break;
+
+ case ICMPMSG(ICMP_TYPE_ECHOREPLY,ICMP_CODE_ECHO):
+ if (q_count(&(icmp->icmp_echoreplies)) < icmp->icmp_maxreplies) {
+ /* We're keeping this packet, put it on the queue and don't
+ free it in the driver. */
+ q_enqueue(&(icmp->icmp_echoreplies),(queue_t *) buf);
+ res = ETH_KEEP;
+ }
+ break;
+
+ default:
+ res = ETH_DROP;
+ }
+
+ return res;
+}
+
+
+/* *********************************************************************
+ * _ICMP_INIT(ipi)
+ *
+ * Initialize the ICMP layer.
+ *
+ * Input parameters:
+ * ipi - ipinfo structure of IP layer to attach to
+ *
+ * Return value:
+ * icmp_info_t structure or NULL if error occurs
+ ********************************************************************* */
+
+icmp_info_t *_icmp_init(ip_info_t *ipi)
+{
+ icmp_info_t *icmp;
+
+ icmp = (icmp_info_t *) KMALLOC(sizeof(icmp_info_t),0);
+ if (!icmp) return NULL;
+
+ icmp->icmp_ipinfo = ipi;
+ q_init(&(icmp->icmp_echoreplies));
+ icmp->icmp_maxreplies = 0;
+
+ _ip_register(ipi,IPPROTO_ICMP,icmp_rx_callback,icmp);
+
+ return icmp;
+}
+
+/* *********************************************************************
+ * _ICMP_UNINIT(icmp)
+ *
+ * Un-initialize the ICMP layer.
+ *
+ * Input parameters:
+ * icmp - icmp_info_t structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void _icmp_uninit(icmp_info_t *icmp)
+{
+ _ip_deregister(icmp->icmp_ipinfo,IPPROTO_ICMP);
+
+ KFREE(icmp);
+}
+
+
+/* *********************************************************************
+ * _ICMP_PING(icmp,dest,seq,len)
+ *
+ * Transmit an ICMP echo request and wait for a reply.
+ *
+ * Input parameters:
+ * icmp - icmp_info_t structure
+ * dest - destination IP address
+ * seq - sequence number for ICMP packet
+ * len - length of data portion of ICMP packet
+ *
+ * Return value:
+ * <0 = error
+ * 0 = timeout
+ * >0 = reply received
+ ********************************************************************* */
+
+int _icmp_ping(icmp_info_t *icmp,uint8_t *dest,int seq,int len)
+{
+ ebuf_t *buf;
+ int64_t timer;
+ uint16_t cksum;
+ uint8_t *icmphdr;
+ uint16_t id;
+ int idx;
+ int result = 0;
+
+ /*
+ * Get an ebuf
+ */
+
+ buf = _ip_alloc(icmp->icmp_ipinfo);
+ if (buf == NULL) return -1;
+
+ /*
+ * Remember where the ICMP header is going to be so we can
+ * calculate the checksum later.
+ */
+
+ icmphdr = buf->eb_ptr;
+
+ id = (uint16_t) cfe_ticks;
+
+ /*
+ * Construct the ICMP header and data portion.
+ */
+
+ ebuf_append_u8(buf,8); /* echo message */
+ ebuf_append_u8(buf,0); /* code = 0 */
+ ebuf_append_u16_be(buf,0); /* empty checksum for now */
+ ebuf_append_u16_be(buf,id); /* packet ID */
+ ebuf_append_u16_be(buf,((uint16_t)seq)); /* sequence # */
+
+ for (idx = 0; idx < len; idx++) {
+ ebuf_append_u8(buf,((idx+0x40)&0xFF)); /* data */
+ }
+
+ /*
+ * Calculate and install the checksum
+ */
+
+ cksum = ~ip_chksum(0,icmphdr,ebuf_length(buf));
+ icmphdr[2] = (cksum >> 8) & 0xFF;
+ icmphdr[3] = (cksum & 0xFF);
+
+ /*
+ * Transmit the ICMP echo
+ */
+
+ icmp->icmp_maxreplies = 1; /* allow ICMP replies */
+ _ip_send(icmp->icmp_ipinfo,buf,dest,IPPROTO_ICMP);
+ buf = NULL;
+
+ /*
+ * Wait for a reply
+ */
+
+ TIMER_SET(timer,2*CFE_HZ);
+
+ while (!TIMER_EXPIRED(timer)) {
+
+ POLL();
+ buf = (ebuf_t *) q_deqnext(&(icmp->icmp_echoreplies));
+
+ /* If we get a packet, make sure it matches. */
+
+ if (buf) {
+ uint16_t rxid,rxseq;
+
+ cksum = ip_chksum(0,buf->eb_ptr,ebuf_length(buf));
+ if (cksum == 0xFFFF) {
+ ebuf_skip(buf,2);
+ ebuf_skip(buf,2); /* skip checksum */
+ ebuf_get_u16_be(buf,rxid);
+ ebuf_get_u16_be(buf,rxseq);
+
+ if ((id == rxid) && ((uint16_t) seq == rxseq)) {
+ result = 1;
+ break;
+ }
+ }
+ _ip_free(icmp->icmp_ipinfo,buf);
+ }
+ }
+
+ /*
+ * Don't accept any more replies.
+ */
+
+ icmp->icmp_maxreplies = 0; /* allow ICMP replies */
+
+ if (buf) _ip_free(icmp->icmp_ipinfo,buf);
+
+ return result;
+
+}
diff --git a/cfe/cfe/net/net_ip.c b/cfe/cfe/net/net_ip.c
new file mode 100755
index 0000000..86303e2
--- /dev/null
+++ b/cfe/cfe/net/net_ip.c
@@ -0,0 +1,722 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Internet Protocol File: net_ip.c
+ *
+ * This module implements the IP layer (RFC791)
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+
+#include "net_ip.h"
+#include "net_ip_internal.h"
+
+#include "cfe_error.h"
+
+/* *********************************************************************
+ * Forward declarations
+ ********************************************************************* */
+
+static int ip_rx_callback(ebuf_t *buf,void *ref);
+
+/* *********************************************************************
+ * _ip_alloc(ipi)
+ *
+ * Allocate an ebuf and reserve space for the IP header in it.
+ *
+ * Input parameters:
+ * ipi - IP stack information
+ *
+ * Return value:
+ * ebuf - an ebuf, or NULL if there are none left
+ ********************************************************************* */
+
+ebuf_t *_ip_alloc(ip_info_t *ipi)
+{
+ ebuf_t *buf;
+
+ buf = eth_alloc(ipi->eth_info,ipi->ip_port);
+
+ if (buf == NULL) return buf;
+
+ ebuf_seek(buf,IPHDR_LENGTH);
+ ebuf_setlength(buf,0);
+
+ return buf;
+}
+
+
+/* *********************************************************************
+ * ip_chksum(initcksum,ptr,len)
+ *
+ * Do an IP checksum for the specified buffer. You can pass
+ * an initial checksum if you're continuing a previous checksum
+ * calculation, such as for UDP headers and pseudoheaders.
+ *
+ * Input parameters:
+ * initcksum - initial checksum (usually zero)
+ * ptr - pointer to buffer to checksum
+ * len - length of data in bytes
+ *
+ * Return value:
+ * checksum (16 bits)
+ ********************************************************************* */
+
+uint16_t ip_chksum(uint16_t initcksum,uint8_t *ptr,int len)
+{
+ unsigned int cksum;
+ int idx;
+ int odd;
+
+ cksum = (unsigned int) initcksum;
+
+ odd = len & 1;
+ len -= odd;
+
+ for (idx = 0; idx < len; idx += 2) {
+ cksum += ((unsigned long) ptr[idx] << 8) + ((unsigned long) ptr[idx+1]);
+ }
+
+ if (odd) { /* buffer is odd length */
+ cksum += ((unsigned long) ptr[idx] << 8);
+ }
+
+ /*
+ * Fold in the carries
+ */
+
+ while (cksum >> 16) {
+ cksum = (cksum & 0xFFFF) + (cksum >> 16);
+ }
+
+ return cksum;
+}
+
+
+/* *********************************************************************
+ * _ip_send(ipi,buf,destaddr,proto)
+ *
+ * Send an IP datagram. We only support non-fragmented datagrams
+ * at this time.
+ *
+ * Input parameters:
+ * ipi - IP stack information
+ * buf - an ebuf
+ * destaddr - destination IP address
+ * proto - IP protocol number
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int _ip_send(ip_info_t *ipi,ebuf_t *buf,uint8_t *destaddr,uint8_t proto)
+{
+ uint16_t cksum;
+ uint8_t masksrc[IP_ADDR_LEN];
+ uint8_t maskdest[IP_ADDR_LEN];
+ int pktlen;
+ uint8_t *ptr;
+
+ /* Move to the beginning of the IP hdeader */
+
+ ebuf_seek(buf,-IPHDR_LENGTH);
+
+ pktlen = ebuf_length(buf) + IPHDR_LENGTH;
+
+ ipi->ip_id++;
+
+ /* Insert the IP header */
+
+ ebuf_put_u8(buf,IPHDR_VER_4 | IPHDR_LEN_20);
+ ebuf_put_u8(buf,IPHDR_TOS_DEFAULT);
+ ebuf_put_u16_be(buf,pktlen);
+ ebuf_put_u16_be(buf,ipi->ip_id);
+ ebuf_put_u16_be(buf,0);
+ ebuf_put_u8(buf,IPHDR_TTL_DEFAULT);
+ ebuf_put_u8(buf,proto);
+ ebuf_put_u16_be(buf,0); /* checksum */
+ ebuf_put_bytes(buf,ipi->net_info.ip_addr,IP_ADDR_LEN);
+ ebuf_put_bytes(buf,destaddr,IP_ADDR_LEN);
+
+ /* adjust pointer and add in the header length */
+
+ ebuf_prepend(buf,IPHDR_LENGTH);
+
+ /* Checksum the header */
+
+ ptr = ebuf_ptr(buf);
+ cksum = ip_chksum(0,ptr,IPHDR_LENGTH);
+ cksum = ~cksum;
+ ptr[10] = (cksum >> 8) & 0xFF;
+ ptr[11] = (cksum >> 0) & 0xFF;
+
+ /*
+ * If sending to the IP broadcast address,
+ * send to local broadcast.
+ */
+
+ if (ip_addrisbcast(destaddr)) {
+ eth_send(buf,(uint8_t *) eth_broadcast);
+ eth_free(buf);
+ return 0;
+ }
+
+ /*
+ * If the mask has not been set, don't try to
+ * determine if we should use the gateway or not.
+ */
+
+ if (ip_addriszero(ipi->net_info.ip_netmask)) {
+ return _arp_lookup_and_send(ipi,buf,destaddr);
+ }
+
+ /*
+ * Compute (dest-addr & netmask) and (my-addr & netmask)
+ */
+
+ ip_mask(masksrc,destaddr,ipi->net_info.ip_netmask);
+ ip_mask(maskdest,ipi->net_info.ip_addr,ipi->net_info.ip_netmask);
+
+ /*
+ * if destination and my address are on the same subnet,
+ * send the packet directly. Otherwise, send via
+ * the gateway.
+ */
+
+ if (ip_compareaddr(masksrc,maskdest) == 0) {
+ return _arp_lookup_and_send(ipi,buf,destaddr);
+ }
+ else {
+ /* if no gw configured, drop packet */
+ if (ip_addriszero(ipi->net_info.ip_gateway)) {
+ eth_free(buf); /* silently drop */
+ return 0;
+ }
+ else {
+ return _arp_lookup_and_send(ipi,buf,ipi->net_info.ip_gateway);
+ }
+ }
+
+}
+
+
+/* *********************************************************************
+ * ip_rx_callback(buf,ref)
+ *
+ * Receive callback for IP packets. This routine is called
+ * by the Ethernet datalink. We look up a suitable protocol
+ * handler and pass the packet off.
+ *
+ * Input parameters:
+ * buf - ebuf we received
+ * ref - reference data from the ethernet datalink
+ *
+ * Return value:
+ * ETH_KEEP to keep the packet
+ * ETH_DROP to drop the packet
+ ********************************************************************* */
+
+static int ip_rx_callback(ebuf_t *buf,void *ref)
+{
+ ip_info_t *ipi = ref;
+ uint8_t tmp;
+ int hdrlen;
+ uint8_t *hdr;
+ uint16_t origchksum;
+ uint16_t calcchksum;
+ uint16_t length;
+ uint16_t tmp16;
+ uint8_t proto;
+ uint8_t srcip[IP_ADDR_LEN];
+ uint8_t dstip[IP_ADDR_LEN];
+ ip_protodisp_t *pdisp;
+ int res;
+ int idx;
+
+ hdr = ebuf_ptr(buf); /* save current posn */
+
+ ebuf_get_u8(buf,tmp); /* version and header length */
+
+ /*
+ * Check IP version
+ */
+
+ if ((tmp & 0xF0) != IPHDR_VER_4) {
+ goto drop; /* not IPV4 */
+ }
+ hdrlen = (tmp & 0x0F) * 4;
+
+ /*
+ * Check header size
+ */
+
+ if (hdrlen < IPHDR_LENGTH) {
+ goto drop; /* header < 20 bytes */
+ }
+
+ /*
+ * Check the checksum
+ */
+ origchksum = ((uint16_t) hdr[10] << 8) | (uint16_t) hdr[11];
+ hdr[10] = hdr[11] = 0;
+ calcchksum = ~ip_chksum(0,hdr,hdrlen);
+ if (calcchksum != origchksum) {
+ goto drop;
+ }
+
+ /*
+ * Okay, now go back and check other fields.
+ */
+
+ ebuf_skip(buf,1); /* skip TOS field */
+
+ ebuf_get_u16_be(buf,length);
+ ebuf_skip(buf,2); /* skip ID field */
+
+ ebuf_get_u16_be(buf,tmp16); /* get Fragment Offset field */
+
+ /*
+ * If the fragment offset field is nonzero, or the
+ * "more fragments" bit is set, then this is a packet
+ * fragment. Our trivial IP implementation does not
+ * deal with fragments, so drop the packets.
+ */
+ if ((tmp16 & (IPHDR_FRAGOFFSET | IPHDR_MOREFRAGMENTS)) != 0) {
+ goto drop; /* packet is fragmented */
+ }
+
+ ebuf_skip(buf,1); /* skip TTL */
+ ebuf_get_u8(buf,proto); /* get protocol */
+ ebuf_skip(buf,2); /* skip checksum */
+
+ ebuf_get_bytes(buf,srcip,IP_ADDR_LEN);
+ ebuf_get_bytes(buf,dstip,IP_ADDR_LEN);
+
+ ebuf_skip(buf,hdrlen-IPHDR_LENGTH); /* skip rest of header */
+
+ ebuf_setlength(buf,length-hdrlen); /* set length to just data portion */
+
+ /*
+ * If our address is not set, let anybody in. We need this to
+ * properly pass up DHCP replies that get forwarde through routers.
+ * Otherwise, only let in matching addresses or broadcasts.
+ */
+
+ if (!ip_addriszero(ipi->net_info.ip_addr)) {
+ if ((ip_compareaddr(dstip,ipi->net_info.ip_addr) != 0) &&
+ !(ip_addrisbcast(dstip))) {
+ goto drop; /* not for us */
+ }
+ }
+
+ /*
+ * ebuf's pointer now starts at beginning of protocol data
+ */
+
+ /*
+ * Find matching protocol dispatch
+ */
+
+ pdisp = ipi->ip_protocols;
+ res = ETH_DROP;
+ for (idx = 0; idx < IP_MAX_PROTOCOLS; idx++) {
+ if (pdisp->cb && (pdisp->protocol == proto)) {
+ res = (*(pdisp->cb))(pdisp->ref,buf,dstip,srcip);
+ break;
+ }
+ pdisp++;
+ }
+
+
+ return res;
+
+drop:
+ return ETH_DROP;
+}
+
+
+/* *********************************************************************
+ * _ip_init(eth)
+ *
+ * Initialize the IP layer, attaching it to an underlying Ethernet
+ * datalink interface.
+ *
+ * Input parameters:
+ * eth - Ethernet datalink information
+ *
+ * Return value:
+ * ip_info pointer (IP stack information) or NULL if error
+ ********************************************************************* */
+
+ip_info_t *_ip_init(ether_info_t *eth)
+{
+ ip_info_t *ipi;
+ int8_t ipproto[2];
+
+ /*
+ * Allocate IP stack info
+ */
+
+ ipi = KMALLOC(sizeof(ip_info_t),0);
+ if (ipi == NULL) return NULL;
+
+ memset(ipi,0,sizeof(ip_info_t));
+
+ ipi->eth_info = eth;
+
+ /*
+ * Initialize ARP
+ */
+
+ if (_arp_init(ipi) < 0) {
+ KFREE(ipi);
+ return NULL;
+ }
+
+ /*
+ * Open the Ethernet portal for IP packets
+ */
+
+ ipproto[0] = (PROTOSPACE_IP >> 8) & 0xFF; ipproto[1] = PROTOSPACE_IP & 0xFF;
+ ipi->ip_port = eth_open(ipi->eth_info,ETH_PTYPE_DIX,ipproto,ip_rx_callback,ipi);
+
+ if (ipi->ip_port < 0) {
+ _arp_uninit(ipi);
+ KFREE(ipi);
+ return NULL;
+ }
+
+ return ipi;
+}
+
+
+/* *********************************************************************
+ * _ip_uninit(ipi)
+ *
+ * Un-initialize the IP layer, freeing resources
+ *
+ * Input parameters:
+ * ipi - IP stack information
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void _ip_uninit(ip_info_t *ipi)
+{
+ /*
+ * Close the IP portal
+ */
+
+ eth_close(ipi->eth_info,ipi->ip_port);
+
+ /*
+ * Turn off the ARP layer.
+ */
+
+ _arp_uninit(ipi);
+
+
+ /*
+ * free strings containing the domain and host names
+ */
+
+ if (ipi->net_info.ip_domain) {
+ KFREE(ipi->net_info.ip_domain);
+ }
+
+ if (ipi->net_info.ip_hostname) {
+ KFREE(ipi->net_info.ip_hostname);
+ }
+
+ /*
+ * Free the stack information
+ */
+
+ KFREE(ipi);
+}
+
+
+/* *********************************************************************
+ * _ip_timer_tick(ipi)
+ *
+ * Called once per second while the IP stack is active.
+ *
+ * Input parameters:
+ * ipi - ip stack information
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+void _ip_timer_tick(ip_info_t *ipi)
+{
+ _arp_timer_tick(ipi);
+}
+
+
+/* *********************************************************************
+ * _ip_free(ipi,buf)
+ *
+ * Free an ebuf allocated via _ip_alloc
+ *
+ * Input parameters:
+ * ipi - IP stack information
+ * buf - ebuf to free
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void _ip_free(ip_info_t *ipi,ebuf_t *buf)
+{
+ eth_free(buf);
+}
+
+/* *********************************************************************
+ * _ip_getaddr(ipi,buf)
+ *
+ * Return our IP address (is this used?)
+ *
+ * Input parameters:
+ * ipi - IP stack information
+ * buf - pointer to 4-byte buffer to receive IP address
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void _ip_getaddr(ip_info_t *ipi,uint8_t *buf)
+{
+ memcpy(buf,ipi->net_info.ip_addr,IP_ADDR_LEN);
+}
+
+/* *********************************************************************
+ * _ip_getparam(ipi,param)
+ *
+ * Return the value of an IP parameter (address, netmask, etc.).
+ * The return value may need to be coerced if it's not normally
+ * a uint8_t* pointer.
+ *
+ * Input parameters:
+ * ipi - IP stack information
+ * param - parameter number
+ *
+ * Return value:
+ * parameter value, or NULL if the parameter is invalid or
+ * not set.
+ ********************************************************************* */
+
+uint8_t *_ip_getparam(ip_info_t *ipinfo,int param)
+{
+ uint8_t *ret = NULL;
+
+ switch (param) {
+ case NET_IPADDR:
+ ret = ipinfo->net_info.ip_addr;
+ break;
+ case NET_NETMASK:
+ ret = ipinfo->net_info.ip_netmask;
+ break;
+ case NET_GATEWAY:
+ ret = ipinfo->net_info.ip_gateway;
+ break;
+ case NET_NAMESERVER:
+ ret = ipinfo->net_info.ip_nameserver;
+ break;
+ case NET_HWADDR:
+ ret = ipinfo->arp_hwaddr;
+ break;
+ case NET_DOMAIN:
+ ret = ipinfo->net_info.ip_domain;
+ break;
+ case NET_HOSTNAME:
+ ret = ipinfo->net_info.ip_hostname;
+ break;
+ case NET_SPEED:
+ return NULL;
+ break;
+ case NET_LOOPBACK:
+ return NULL;
+ break;
+ }
+
+ return ret;
+}
+
+/* *********************************************************************
+ * _ip_getparam(ipi,param,value)
+ *
+ * Set the value of an IP parameter (address, netmask, etc.).
+ * The value may need to be coerced if it's not normally
+ * a uint8_t* pointer.
+ *
+ * Input parameters:
+ * ipi - IP stack information
+ * param - parameter number
+ * value - parameter's new value
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+int _ip_setparam(ip_info_t *ipinfo,int param,uint8_t *ptr)
+{
+ int res = -1;
+
+ switch (param) {
+ case NET_IPADDR:
+ memcpy(ipinfo->net_info.ip_addr,ptr,IP_ADDR_LEN);
+ _arp_send_gratuitous(ipinfo);
+ res = 0;
+ break;
+ case NET_NETMASK:
+ memcpy(ipinfo->net_info.ip_netmask,ptr,IP_ADDR_LEN);
+ res = 0;
+ break;
+ case NET_GATEWAY:
+ memcpy(ipinfo->net_info.ip_gateway,ptr,IP_ADDR_LEN);
+ res = 0;
+ break;
+ case NET_NAMESERVER:
+ memcpy(ipinfo->net_info.ip_nameserver,ptr,IP_ADDR_LEN);
+ res = 0;
+ break;
+ case NET_DOMAIN:
+ if (ipinfo->net_info.ip_domain) {
+ KFREE(ipinfo->net_info.ip_domain);
+ ipinfo->net_info.ip_domain = NULL;
+ }
+ if (ptr) ipinfo->net_info.ip_domain = (uint8_t*)strdup((char *) ptr);
+ break;
+ case NET_HOSTNAME:
+ if (ipinfo->net_info.ip_hostname) {
+ KFREE(ipinfo->net_info.ip_hostname);
+ ipinfo->net_info.ip_hostname = NULL;
+ }
+ if (ptr) ipinfo->net_info.ip_hostname = (uint8_t*)strdup((char *) ptr);
+ break;
+ case NET_HWADDR:
+ memcpy(ipinfo->arp_hwaddr,ptr,ENET_ADDR_LEN);
+ eth_sethwaddr(ipinfo->eth_info,ptr);
+ res = 0;
+ break;
+ case NET_SPEED:
+ res = eth_setspeed(ipinfo->eth_info,*(int *)ptr);
+ break;
+ case NET_LOOPBACK:
+ res = eth_setloopback(ipinfo->eth_info,*(int *)ptr);
+ break;
+ }
+
+ return res;
+}
+
+/* *********************************************************************
+ * _ip_register(ipinfo,proto,cb)
+ *
+ * Register a protocol handler with the IP layer. IP client
+ * protocols such as UDP, ICMP, etc. call this to register their
+ * callbacks.
+ *
+ * Input parameters:
+ * ipinfo - IP stack information
+ * proto - IP protocol number
+ * cb - callback routine to register
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void _ip_register(ip_info_t *ipinfo,
+ int proto,
+ int (*cb)(void *ref,ebuf_t *buf,uint8_t *dst,uint8_t *src),void *ref)
+{
+ int idx;
+
+ for (idx = 0; idx < IP_MAX_PROTOCOLS; idx++) {
+ if (ipinfo->ip_protocols[idx].cb == NULL) break;
+ }
+
+ if (idx == IP_MAX_PROTOCOLS) return;
+
+ ipinfo->ip_protocols[idx].protocol = (uint8_t) proto;
+ ipinfo->ip_protocols[idx].cb = cb;
+ ipinfo->ip_protocols[idx].ref = ref;
+}
+
+
+/* *********************************************************************
+ * _ip_deregister(ipinfo,proto)
+ *
+ * Deregister an IP protocol.
+ *
+ * Input parameters:
+ * ipinfo - IP stack information
+ * proto - protocol number
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void _ip_deregister(ip_info_t *ipinfo,int proto)
+{
+ int idx;
+
+ for (idx = 0; idx < IP_MAX_PROTOCOLS; idx++) {
+ if (ipinfo->ip_protocols[idx].protocol == (uint8_t) proto) {
+ ipinfo->ip_protocols[idx].protocol = 0;
+ ipinfo->ip_protocols[idx].ref = 0;
+ ipinfo->ip_protocols[idx].cb = NULL;
+ }
+ }
+}
+
diff --git a/cfe/cfe/net/net_ip.h b/cfe/cfe/net/net_ip.h
new file mode 100755
index 0000000..7b1b4be
--- /dev/null
+++ b/cfe/cfe/net/net_ip.h
@@ -0,0 +1,159 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * IP Protocol Definitions File: net_ip.h
+ *
+ * This is the main include file for the CFE network stack.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+/* *********************************************************************
+ * Global info
+ ********************************************************************* */
+
+#ifndef IP_ADDR_LEN
+#define IP_ADDR_LEN 4
+#endif
+
+typedef struct ip_info_s ip_info_t;
+
+typedef struct net_info_s {
+ /* Configuration info for IP interface */
+ uint8_t ip_addr[IP_ADDR_LEN];
+ uint8_t ip_netmask[IP_ADDR_LEN];
+ uint8_t ip_gateway[IP_ADDR_LEN];
+ uint8_t ip_nameserver[IP_ADDR_LEN];
+ uint8_t *ip_domain;
+ uint8_t *ip_hostname;
+} net_info_t;
+
+/* *********************************************************************
+ * ARP Information
+ ********************************************************************* */
+
+int _arp_lookup_and_send(ip_info_t *ipi,ebuf_t *buf,uint8_t *dest);
+void _arp_timer_tick(ip_info_t *ipi);
+int _arp_init(ip_info_t *ipi);
+void _arp_uninit(ip_info_t *ipi);
+void _arp_add(ip_info_t *ipi,uint8_t *destip,uint8_t *desthw);
+void _arp_send_gratuitous(ip_info_t *ipi);
+uint8_t *_arp_lookup(ip_info_t *ipi,uint8_t *destip);
+int _arp_enumerate(ip_info_t *ipi,int entrynum,uint8_t *ipaddr,uint8_t *hwaddr);
+int _arp_delete(ip_info_t *ipi,uint8_t *ipaddr);
+
+
+/* *********************************************************************
+ * IP protocol
+ ********************************************************************* */
+
+
+#define IPPROTO_TCP 6
+#define IPPROTO_UDP 17
+#define IPPROTO_ICMP 1
+
+int _ip_send(ip_info_t *ipi,ebuf_t *buf,uint8_t *destaddr,uint8_t proto);
+ip_info_t *_ip_init(ether_info_t *);
+void _ip_timer_tick(ip_info_t *ipi);
+void _ip_uninit(ip_info_t *ipi);
+ebuf_t *_ip_alloc(ip_info_t *ipi);
+void _ip_free(ip_info_t *ipi,ebuf_t *buf);
+void _ip_getaddr(ip_info_t *ipi,uint8_t *buf);
+uint8_t *_ip_getparam(ip_info_t *ipinfo,int param);
+int _ip_setparam(ip_info_t *ipinfo,int param,uint8_t *ptr);
+uint16_t ip_chksum(uint16_t initcksum,uint8_t *ptr,int len);
+void _ip_deregister(ip_info_t *ipinfo,int proto);
+void _ip_register(ip_info_t *ipinfo,
+ int proto,
+ int (*cb)(void *ref,ebuf_t *buf,uint8_t *dst,uint8_t *src),void *ref);
+
+
+#define ip_mask(dest,a,b) (dest)[0] = (a)[0] & (b)[0] ; \
+ (dest)[1] = (a)[1] & (b)[1] ; \
+ (dest)[2] = (a)[2] & (b)[2] ; \
+ (dest)[3] = (a)[3] & (b)[3]
+
+#define ip_compareaddr(a,b) memcmp(a,b,IP_ADDR_LEN)
+
+#define ip_addriszero(a) (((a)[0]|(a)[1]|(a)[2]|(a)[3]) == 0)
+#define ip_addrisbcast(a) ((a[0] == 0xFF) && (a[1] == 0xFF) && (a[2] == 0xFF) && (a[3] == 0xFF))
+
+#ifndef NET_IPADDR
+#define NET_IPADDR 0
+#define NET_NETMASK 1
+#define NET_GATEWAY 2
+#define NET_NAMESERVER 3
+#define NET_HWADDR 4
+#define NET_DOMAIN 5
+#define NET_HOSTNAME 6
+#define NET_SPEED 7
+#define NET_LOOPBACK 8
+#endif
+
+/* *********************************************************************
+ * UDP Protocol
+ ********************************************************************* */
+
+typedef struct udp_info_s udp_info_t;
+
+int _udp_socket(udp_info_t *info,uint16_t port);
+void _udp_close(udp_info_t *info,int s);
+int _udp_send(udp_info_t *info,int s,ebuf_t *buf,uint8_t *dest);
+udp_info_t *_udp_init(ip_info_t *ipi,void *ref);
+void _udp_uninit(udp_info_t *info);
+int _udp_bind(udp_info_t *info,int s,uint16_t port);
+int _udp_connect(udp_info_t *info,int s,uint16_t port);
+ebuf_t *_udp_recv(udp_info_t *info,int s);
+ebuf_t *_udp_alloc(udp_info_t *info);
+void _udp_free(udp_info_t *info,ebuf_t *buf);
+
+/* *********************************************************************
+ * ICMP protocol
+ ********************************************************************* */
+
+typedef struct icmp_info_s icmp_info_t;
+
+icmp_info_t *_icmp_init(ip_info_t *ipi);
+void _icmp_uninit(icmp_info_t *icmp);
+
+int _icmp_ping(icmp_info_t *icmp,uint8_t *ipaddr,int seq,int len);
+
+
diff --git a/cfe/cfe/net/net_ip_internal.h b/cfe/cfe/net/net_ip_internal.h
new file mode 100644
index 0000000..94401e2
--- /dev/null
+++ b/cfe/cfe/net/net_ip_internal.h
@@ -0,0 +1,128 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Internal IP structures File: net_ip_internal.h
+ *
+ * This module contains non-public IP stack constants,
+ * structures, and function prototypes.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+/* *********************************************************************
+ * ARP Protocol
+ ********************************************************************* */
+
+#define ARP_OPCODE_REQUEST 1
+#define ARP_OPCODE_REPLY 2
+
+#define ARP_HWADDRSPACE_ETHERNET 1
+
+#define PROTOSPACE_IP 0x0800
+#define PROTOSPACE_ARP 0x0806
+
+/* Foxconn add start by Cliff Wang, 03/23/2010 */
+#define PROTOSPACE_NMRP 0x0912
+/* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+#define ARP_KEEP_TIMER 60
+#define ARP_QUERY_TIMER 1
+#define ARP_QUERY_RETRIES 4
+#define ARP_TXWAIT_MAX 2
+#define ARP_TABLE_SIZE 8
+
+typedef enum { ae_unused, ae_arping, ae_established } arpstate_t;
+
+typedef struct arpentry_s {
+ arpstate_t ae_state;
+ int ae_usage;
+ int ae_timer;
+ int ae_retries;
+ int ae_permanent;
+ uint8_t ae_ipaddr[IP_ADDR_LEN];
+ uint8_t ae_ethaddr[ENET_ADDR_LEN];
+ queue_t ae_txqueue;
+} arpentry_t;
+
+
+/* *********************************************************************
+ * IP Protocol
+ ********************************************************************* */
+
+#define IPHDR_VER_4 0x40
+#define IPHDR_LEN_20 0x05
+#define IPHDR_LENGTH 20
+#define IPHDR_TOS_DEFAULT 0x00
+#define IPHDR_TTL_DEFAULT 100
+
+#define IPHDR_RESERVED 0x8000
+#define IPHDR_DONTFRAGMENT 0x4000
+#define IPHDR_MOREFRAGMENTS 0x2000
+#define IPHDR_FRAGOFFSET 0x01FFF
+
+typedef struct ip_protodisp_s {
+ uint8_t protocol;
+ int (*cb)(void *ref,ebuf_t *buf,uint8_t *dst,uint8_t *src);
+ void *ref;
+} ip_protodisp_t;
+
+#define IP_MAX_PROTOCOLS 4
+
+
+struct ip_info_s {
+ net_info_t net_info;
+
+ /* Ethernet info */
+ ether_info_t *eth_info;
+
+ /* Info specific to IP */
+ uint16_t ip_id;
+ int ip_port;
+
+ /* IP protocol dispatch table */
+ ip_protodisp_t ip_protocols[IP_MAX_PROTOCOLS];
+
+ /* Info specific to ARP */
+ arpentry_t *arp_table;
+ int arp_port;
+ uint8_t arp_hwaddr[ENET_ADDR_LEN];
+};
+
+
diff --git a/cfe/cfe/net/net_nmrp.c b/cfe/cfe/net/net_nmrp.c
new file mode 100755
index 0000000..696d04d
--- /dev/null
+++ b/cfe/cfe/net/net_nmrp.c
@@ -0,0 +1,656 @@
+#include "bsp_config.h"
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_ioctl.h"
+#include "cfe_timer.h"
+
+#include "cfe_error.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+
+#include "cfe_timer.h"
+
+#include "net_ip.h"
+#include "net_ip_internal.h"
+#include "net_api.h"
+
+#include "env_subr.h"
+
+#if CFG_TCP
+#include "net_tcp.h"
+#endif
+
+#include "ui_command.h"
+
+typedef struct net_ctx_s {
+ /* Global info */
+ int64_t timer;
+
+ /* device name */
+ char *devname;
+
+ /* Run-time info for IP interface */
+ ip_info_t *ipinfo;
+
+ /* Info for Ethernet interface */
+ ether_info_t *ethinfo;
+
+ /* Info specific to UDP */
+ udp_info_t *udpinfo;
+
+ /* Info specific to ICMP */
+ icmp_info_t *icmpinfo;
+
+#if CFG_TCP
+ /* Info specific to TCP */
+ tcp_info_t *tcpinfo;
+#endif
+} net_ctx_t;
+
+
+#pragma pack(1)
+
+typedef uint8_t BYTE;
+typedef uint16_t WORD;
+typedef uint32_t DWORD;
+
+/* NMRP timeouts */
+enum _nmrp_timeouts_ {
+ NMRP_TIMEOUT_REQ = 1/2, /* 0.5 sec */
+ NMRP_TIMEOUT_LISTEN = 3, /* 3 sec */
+ NMRP_TIMEOUT_ACTIVE = 60000, /* 1 minute */
+ NMRP_TIMEOUT_CLOSE = 6000, /* 6 sec */
+ NMRP_TIMEOUT_ADVERTISE = 500 /* 0.5 sec */
+};
+
+enum _nmrp_errors_ {
+ NMRP_ERR_NONE = 0,
+ NMRP_ERR_MSG_INVALID_LEN,
+ NMRP_ERR_MSG_TOO_LONG,
+ NMRP_ERR_MSG_TOO_MANY_OPT,
+ NMRP_ERR_MSG_UNKNOWN_OPT,
+ NMRP_ERR_MSG_INVALID_OPT,
+ NMRP_ERR_NO_BUF,
+ NMRP_ERR_GENERAL
+};
+
+/* NMRP codes */
+enum _nmrp_codes_ {
+ NMRP_CODE_ADVERTISE = 0x01,
+ NMRP_CODE_CONF_REQ = 0x02,
+ NMRP_CODE_CONF_ACK = 0x03,
+ NMRP_CODE_CLOSE_REQ = 0x04,
+ NMRP_CODE_CLOSE_ACK = 0x05,
+ NMRP_CODE_KEEP_ALIVE_REQ = 0x06,
+ NMRP_CODE_KEEP_ALIVE_ACK = 0x07,
+ NMRP_CODE_TFTP_UL_REQ = 0x10
+};
+
+/* NMRP option types */
+enum _nmrp_option_types_ {
+ NMRP_OPT_MAGIC_NO = 0x0001,
+ NMRP_OPT_DEV_IP = 0x0002,
+ NMRP_OPT_FW_UP = 0x0101
+};
+
+typedef enum {
+ NMRPC_L2_NO_ERROR = 0,
+ NMRPC_L2_TX_PKT_TOO_LONG,
+ NMRPC_L2_TX_ETHER_PREPEND_FAIL,
+ NMRPC_L2_TX_ERROR,
+ NMRPC_L2_GEN_ERR
+} NMRPC_L2_RET_CODE;
+
+/* NMRP REQ max retries */
+enum _nmrp_req_max_retries_ {
+ NMRP_MAX_RETRY_CONF = 5,
+ NMRP_MAX_RETRY_CLOSE = 9999,
+ NMRP_MAX_RETRY_TFTP_UL = 4
+};
+
+
+enum _nmrp_state_ {
+ NMRP_STATE_LISTEN = 0,
+ NMRP_STATE_CONFIGURE,
+ NMRP_STATE_TRANSFER,
+ NMRP_STATE_CLOSE
+};
+
+#define NMRP_MAX_OPT_PER_MSG (6)
+#define ETHER_NMRP (0x0912)
+
+#define NMRP_HDR_LEN (sizeof(NMRP_MSG) - sizeof(NMRP_OPT))
+#define NMRP_MIN_OPT_LEN (sizeof(NMRP_OPT) - 1)
+
+#define NMRP_MAGIC_NO "\x4E\x54\x47\x52"
+#define NMRP_MAGIC_NO_LEN (sizeof(NMRP_MAGIC_NO) - 1)
+
+typedef struct {
+ uint8_t destMAC[6];
+ uint8_t srcMAC[6];
+ uint16_t etherType;
+} ETHER_HDR;
+
+typedef struct {
+ uint16_t type;
+ uint16_t len;
+ uint8_t value;
+} NMRP_OPT;
+
+typedef struct {
+ uint16_t reserved;
+ uint8_t code;
+ uint8_t id;
+ uint16_t length;
+
+ NMRP_OPT opt;
+} NMRP_MSG;
+
+typedef struct {
+ ETHER_HDR etherHdr;
+ NMRP_MSG nmrpMsg;
+} ETHER_NMRP_PKT;
+
+typedef struct {
+ uint16_t type;
+ uint16_t len;
+
+ union {
+ uint8_t byteVal;
+ uint16_t wordVal;
+ uint32_t dwordVal;
+ const uint8_t *streamVal;
+ } value;
+} NMRP_PARSED_OPT;
+
+typedef struct {
+ uint8_t code;
+ uint8_t id;
+ uint16_t length;
+
+ int numOptions;
+ NMRP_PARSED_OPT options[NMRP_MAX_OPT_PER_MSG];
+} NMRP_PARSED_MSG;
+
+typedef struct {
+ int reqCode;
+ const char reqName[32], respName[32];
+
+ int (* RespParser) (const void *pkt, int pktLen, const BYTE *serverMac, void *userData);
+} NMRP_REQ_CUSTOM;
+
+typedef struct {
+
+ BYTE peerMac[6];
+ BYTE myMac[6];
+
+ DWORD peerIp;
+ DWORD myIp;
+ WORD ipId;
+
+ WORD peerPort;
+ WORD myPort;
+} NET_INFO;
+
+#pragma pack()
+
+#define MIN_ETHER_NMRP_LEN (sizeof(ETHER_HDR) + NMRP_HDR_LEN)
+
+#if 0
+#define HTONCS(constWord) ((((constWord) & 0xff00) >> 8) | (((constWord) & 0xff) << 8))
+#define NTOHCS(constWord) HTONCS(constWord)
+#define HTONCL(constDword) ((((constDword) & 0xff000000) >> 24) | (((constDword) & 0xff0000) >> 8) | (((constDword) & 0xff00) << 8) | (((constDword) & 0xff) << 24))
+#define NTOHCL(constDword) HTONCL(constDword)
+#endif
+
+#define HTONCS(constWord) constWord
+#define NTOHCS(constWord) constWord
+#define HTONCL(constDword) constDword
+#define NTOHCL(constDword) constDword
+/*
+#define IS_NMRP_PKT(etherNmrpPkt, pktLen, parsedNmrpMsg, sourceMAC) \
+ ((pktLen) > MIN_ETHER_NMRP_LEN && (etherNmrpPkt)->etherHdr.etherType == HTONCS(ETHER_NMRP) && \
+ ((sourceMAC) == NULL || memcmp((sourceMAC), (etherNmrpPkt)->etherHdr.srcMAC, 6) == 0) && \
+ NMRP_MsgParsing(&(etherNmrpPkt)->nmrpMsg, (pktLen) - sizeof(ETHER_HDR), (parsedNmrpMsg)) == NMRP_ERR_NONE)
+*/
+
+#define IS_NMRP_PKT(etherNmrpPkt, pktLen, parsedNmrpMsg, sourceMAC) \
+ ((pktLen) > MIN_ETHER_NMRP_LEN && (etherNmrpPkt)->etherHdr.etherType == HTONCS(ETHER_NMRP) && \
+ ((sourceMAC) == NULL || memcmp((sourceMAC), (etherNmrpPkt)->etherHdr.srcMAC, 6) == 0))
+
+static int nmrp_rx_callback(ebuf_t *buf,void *ref);
+int NMRP_MsgParsing(const NMRP_MSG *pkt, int pktLen, NMRP_PARSED_MSG *msg);
+NMRP_PARSED_OPT *NMRP_MsgGetOpt(NMRP_PARSED_MSG *msg, uint16_t optType);
+//int NMRPRequest( const BYTE *serverMac, const BYTE *clientMac, NMRP_REQ_CUSTOM *custom, void *userData);
+static int NMRPConfiguring( const BYTE *serverMac, const BYTE *clientMac, DWORD *ipAddr, DWORD *ipSubnetMask, int *fwUpgrade);
+static int NMRPConfAckParser(const void *pkt, int pktLen, const BYTE *serverMac, void *userData);
+//int NMRPTFTPWaiting(const NET_INFO *netInfo, DWORD *peerIp, WORD *peerPort, WORD *ipId);
+int NMRPTFTPWaiting(void);
+int NMRPKeepAlive(void);
+static int NMRPClosing(void);
+static int NMRPSend(NMRP_REQ_CUSTOM *custom);
+
+int nmrp_server_detected;
+int g_nmrp_config_acked;
+int g_nmrp_close_acked;
+//int g_Listening;
+int g_NMRP_State;
+extern net_ctx_t *netctx;
+
+NET_INFO g_NetInfo;
+//ebuf_t *g_nmrp_txbuf = NULL;
+int g_portal_number;
+NMRP_PARSED_MSG g_nmrpMsg;
+int g_tftp_upgrade_success;
+int g_nmrp_keepalive;//jenny add for fixed NMRP server timeout issue
+unsigned char g_received_packet[1600];
+
+int gpio_control(int gpio, int value);
+extern int32_t _getticks(void); /* return value of CP0 COUNT */
+static unsigned long seed = 1;
+
+void srand(unsigned long local_seed);
+unsigned long rand(void);
+int _start_nmrp(void);
+
+void srand(unsigned long local_seed)
+{
+ seed = local_seed;
+}
+
+unsigned long rand(void)
+{
+
+ long x, hi, lo, t;
+
+ x = seed;
+ hi = x / 127773;
+ lo = x % 127773;
+ t = 16807 * lo - 2836 * hi;
+ if (t <= 0) t += 0x7fffffff;
+ seed = t;
+ return t;
+}
+
+int _start_nmrp (void)
+{
+ uint8_t nmrpproto[2];
+
+ int ret = 0;
+ int ui_cmd_status;
+ int fwUpgrade;
+ int64_t timer;
+ DWORD ipSubnetMask;
+ char buf[512];
+ unsigned char *pIP, *pMask;
+
+ srand( (unsigned long)_getticks());
+
+ //net_init("eth0");
+ nmrpproto[0] = (PROTOSPACE_NMRP >> 8) & 0xFF;
+ nmrpproto[1] = (PROTOSPACE_NMRP & 0xFF);
+ g_tftp_upgrade_success = 0;
+ g_nmrp_keepalive = 0;//jenny add for timeout
+
+ g_portal_number = eth_open(netctx->ethinfo, ETH_PTYPE_DIX, (char*)nmrpproto, nmrp_rx_callback, NULL);
+ if(g_portal_number < 0)
+ {
+ ret = -1;
+ goto _clean_and_exit;
+ }
+
+ eth_gethwaddr(netctx->ethinfo, g_NetInfo.myMac);
+//_retry:
+ g_NMRP_State = NMRP_STATE_LISTEN;
+ nmrp_server_detected = 0;
+ TIMER_SET(timer, NMRP_TIMEOUT_LISTEN*CFE_HZ);
+ while (!TIMER_EXPIRED(timer))
+ {
+ POLL();
+ if(nmrp_server_detected)
+ {
+ xprintf ("find server.\n");
+ break;
+ }
+ }
+
+ if(!nmrp_server_detected)
+ {
+ ret = -1;
+ goto _clean_and_exit;
+ }
+
+ g_nmrp_config_acked = 0;
+
+ if (NMRPConfiguring( g_NetInfo.peerMac, g_NetInfo.myMac, &g_NetInfo.myIp, &ipSubnetMask, &fwUpgrade) == -1)
+ {
+ ret = -1;
+ goto _clean_and_exit;
+ }
+
+ pIP = (unsigned char *)&g_NetInfo.myIp;
+ pMask = (unsigned char *)&ipSubnetMask;
+
+ sprintf(buf, "ifconfig eth0 -addr=%u.%u.%u.%u -mask=%u.%u.%u.%u", *(pIP), *(pIP+1), *(pIP+2), *(pIP+3),
+ *(pMask), *(pMask+1), *(pMask+2), *(pMask+3) );
+ ui_docommand(buf);
+
+
+_retry_tftp:
+
+ NMRPTFTPWaiting();
+ //eth_close(netctx->ethinfo, g_portal_number);
+ //g_portal_number = 0;
+ //net_init("eth0");
+ ui_cmd_status = ui_docommand("tftpd nmrp");
+
+
+ sprintf(buf, "ifconfig eth0 -addr=%u.%u.%u.%u -mask=%u.%u.%u.%u", *(pIP), *(pIP+1), *(pIP+2), *(pIP+3),
+ *(pMask), *(pMask+1), *(pMask+2), *(pMask+3) );
+
+ ui_docommand(buf);
+
+ //net_init("eth0");
+ g_portal_number = eth_open(netctx->ethinfo, ETH_PTYPE_DIX, (char*)nmrpproto, nmrp_rx_callback, NULL);
+
+ if(ui_cmd_status != 0)
+ {
+ goto _retry_tftp;
+ }
+
+ g_nmrp_close_acked = 0;
+ /* Foxconn modified start, zacker,04/07/2008 */
+ /* ui_docommand("nvram erase"); */
+ // nvram_unset("restore_defaults");
+ // nvram_commit();
+ /* Foxconn modified end, zacker,04/07/2008 */
+
+ NMRPClosing();
+ g_tftp_upgrade_success = 1;
+ // gpio_control(7, 1); //turn off power led
+
+_clean_and_exit:
+
+ if(g_portal_number > 0)
+ eth_close(netctx->ethinfo, g_portal_number);
+
+ return ret;
+}
+
+extern void setPowerOnLedOn(void);
+static int nmrp_rx_callback(ebuf_t *buf,void *ref)
+{
+ int pktLen = 0;
+ NMRP_PARSED_MSG nmrpMsg;
+ const ETHER_NMRP_PKT *pkt;
+ unsigned char *p;
+
+ pkt = (const ETHER_NMRP_PKT *)buf->eb_data;
+ pktLen = buf->eb_length + sizeof(ETHER_HDR) - 4;
+
+ p=(unsigned char *)pkt;
+
+ if(g_NMRP_State == NMRP_STATE_LISTEN)
+ {
+ if (IS_NMRP_PKT(pkt, pktLen, &nmrpMsg, NULL) && (*(p+16) == NMRP_CODE_ADVERTISE ) )
+ {
+ if (NMRP_MsgParsing(&(pkt)->nmrpMsg, (pktLen) - sizeof(ETHER_HDR), &nmrpMsg) == NMRP_ERR_NONE)
+ {
+ if(NMRP_MsgGetOpt(&nmrpMsg, NMRP_OPT_MAGIC_NO) != NULL)
+ {
+ memcpy(g_NetInfo.peerMac, buf->eb_data+6, 6);
+ g_NMRP_State = NMRP_STATE_CONFIGURE;
+ nmrp_server_detected = 1;
+ setPowerOnLedOn(); /* Foxconn added for U12H154, turn on TEST LED */
+ }
+ }
+ }
+ }
+ else if(g_NMRP_State == NMRP_STATE_CONFIGURE)
+ {
+ if (IS_NMRP_PKT(pkt, pktLen, &nmrpMsg, NULL) && (*(p+16) == NMRP_CODE_CONF_ACK ) )
+ {
+ memcpy(g_received_packet, pkt, pktLen);
+ pkt = (const ETHER_NMRP_PKT *)g_received_packet;
+ if (NMRP_MsgParsing(&(pkt)->nmrpMsg, (pktLen) - sizeof(ETHER_HDR), &nmrpMsg) == NMRP_ERR_NONE)
+ {
+ if(NMRPConfAckParser(pkt, pktLen, g_NetInfo.peerMac, &nmrpMsg))
+ {
+ g_nmrpMsg = nmrpMsg;
+ g_nmrp_config_acked = 1;
+ g_NMRP_State = NMRP_STATE_TRANSFER;
+ }
+ }
+ }
+ }
+ else if(g_NMRP_State == NMRP_STATE_TRANSFER)
+ {
+ if (IS_NMRP_PKT(pkt, pktLen, &nmrpMsg, NULL) && (*(p+16) == NMRP_CODE_CLOSE_ACK ) )
+ {
+ if (NMRP_MsgParsing(&(pkt)->nmrpMsg, (pktLen) - sizeof(ETHER_HDR), &nmrpMsg) == NMRP_ERR_NONE)
+ {
+ g_NMRP_State =NMRP_STATE_CLOSE;
+ g_nmrp_close_acked = 1;
+ }
+ }
+ }
+
+ return ETH_DROP;
+}
+
+static int NMRP_OptValParsing(NMRP_PARSED_OPT *optParsed, const uint8_t *value)
+{
+ int retVal = NMRP_ERR_NONE;
+
+ switch (optParsed->type) {
+ case NMRP_OPT_MAGIC_NO: /* We require the lenght MUST be correct for the MAGIC-NO option */
+ if (optParsed->len != (NMRP_MIN_OPT_LEN + NMRP_MAGIC_NO_LEN) || memcmp(value, NMRP_MAGIC_NO, NMRP_MAGIC_NO_LEN))
+ {
+ retVal = NMRP_ERR_MSG_INVALID_OPT;
+ }
+ else
+ {
+ optParsed->value.streamVal = value;
+ }
+ break;
+
+ case NMRP_OPT_DEV_IP: /* save the value of IP in the byte stream format, the actual IP is streamVal[0].streamVal[1].streamVal[2].streamVal[3]. */
+ //if ( optParsed->len != (NMRP_MIN_OPT_LEN + 8) || !IsIPAddrValid(ntohl(*(DWORD *) value), ntohl(*(DWORD *) (value + 4))) )
+ if ( optParsed->len != (NMRP_MIN_OPT_LEN + 8) )
+ retVal = NMRP_ERR_MSG_INVALID_OPT;
+ else
+ optParsed->value.streamVal = value;
+ break;
+
+ case NMRP_OPT_FW_UP: /* don't check the length of FW-UP option for future compatibility */
+ break;
+
+ default:
+ retVal = NMRP_ERR_MSG_UNKNOWN_OPT;
+ break;
+ }
+
+ return retVal;
+}
+
+int NMRP_MsgParsing(const NMRP_MSG *pkt, int pktLen, NMRP_PARSED_MSG *msg)
+{
+ if (pktLen < NMRP_HDR_LEN)
+ return NMRP_ERR_MSG_INVALID_LEN;
+
+ msg->code = pkt->code;
+ msg->id = pkt->id;
+
+ if ((msg->length = NTOHCS(pkt->length)) <= pktLen && msg->length >= NMRP_HDR_LEN) {
+ int retVal;
+ uint16_t optLen;
+ NMRP_OPT *opt;
+ NMRP_PARSED_OPT *optParsed;
+
+ opt = (NMRP_OPT *)(((uint8_t *) pkt) + NMRP_HDR_LEN);
+ optParsed = msg->options;
+ msg->numOptions = 0;
+
+ /* use the length indicated in the NMRP header */
+ for (pktLen = msg->length - NMRP_HDR_LEN; pktLen >= NMRP_MIN_OPT_LEN; )
+ {
+ optParsed->type = NTOHCS(opt->type);
+ optParsed->len = optLen = NTOHCS(opt->len);
+
+ if (optParsed->len > pktLen)
+ return NMRP_ERR_MSG_INVALID_OPT;
+
+ if ((retVal = NMRP_OptValParsing(optParsed, &opt->value)) == NMRP_ERR_NONE)
+ {
+ optParsed++;
+
+ if (++msg->numOptions >= NMRP_MAX_OPT_PER_MSG)
+ return NMRP_ERR_MSG_TOO_MANY_OPT;
+ }
+ else if (retVal != NMRP_ERR_MSG_UNKNOWN_OPT)
+ {
+ return NMRP_ERR_MSG_INVALID_OPT;
+ }
+
+ pktLen -= optLen;
+ opt = (NMRP_OPT *)(((uint8_t *) opt) + optLen);
+ }
+ } /* end if the msg->length is larger than the received packet length */
+
+ return pktLen == 0 ? NMRP_ERR_NONE : NMRP_ERR_MSG_INVALID_LEN;
+}
+
+NMRP_PARSED_OPT *NMRP_MsgGetOpt(NMRP_PARSED_MSG *msg, uint16_t optType)
+{
+ NMRP_PARSED_OPT *opt, *optEnd;
+
+ optEnd = &msg->options[msg->numOptions];
+
+ for (opt = msg->options; opt != optEnd; opt++)
+ if (opt->type == optType)
+ break;
+
+ return msg->numOptions == 0 ? NULL : (opt == optEnd ? NULL : opt);
+}
+
+static int NMRPClosing(void)
+{
+ int ret, retries=0;
+ static NMRP_REQ_CUSTOM reqClose = { NMRP_CODE_CLOSE_REQ, "CLOSE-REQ", "CLOSE-ACK", NULL };
+
+ do {
+ ret = NMRPSend(&reqClose);
+ if( !ret)
+ {
+ cfe_sleep(CFE_HZ/2);
+ if(g_nmrp_close_acked)
+ {
+ break;
+ }
+ }
+ } while(++retries <= NMRP_MAX_RETRY_CLOSE);
+
+ return 0;
+}
+
+int NMRPTFTPWaiting(void)
+{
+ static NMRP_REQ_CUSTOM reqTftpUl = { NMRP_CODE_TFTP_UL_REQ, "TFTP-UL-REQ", "TFTP-WRQ", NULL };
+
+ return NMRPSend(&reqTftpUl);
+}
+
+/* Foxconn modify start by Jenny Zhao, 08/07/2008, for fixed timeout issue*/
+int NMRPKeepAlive(void)
+{
+ static NMRP_REQ_CUSTOM reqkeepalive = { NMRP_CODE_KEEP_ALIVE_REQ, "KEEPALIVE_REQ", "KEEPALIVE-ACK", NULL };
+
+ return NMRPSend(&reqkeepalive);
+}
+/* Foxconn modify end by Jenny Zhao, 08/07/2008*/
+
+static int NMRPConfAckParser(const void *pkt, int pktLen, const BYTE *serverMac, void *userData)
+{
+ NMRP_PARSED_MSG *nmrpMsg = (NMRP_PARSED_MSG *) userData;
+
+ return NMRP_MsgGetOpt(nmrpMsg, NMRP_OPT_DEV_IP) != NULL;
+ /*
+ return IS_NMRP_PKT((const ETHER_NMRP_PKT *)pkt, pktLen, nmrpMsg, serverMac) &&
+ nmrpMsg->code == NMRP_CODE_CONF_ACK &&
+ NMRP_MsgGetOpt(nmrpMsg, NMRP_OPT_DEV_IP) != NULL;
+ */
+}
+
+
+static int NMRPConfiguring( const BYTE *serverMac,
+ const BYTE *clientMac,
+ DWORD *ipAddr, DWORD *ipSubnetMask,
+ int *fwUpgrade)
+{
+ //int ret, retries=0;
+ int ret;
+ NMRP_PARSED_OPT *devIp;
+ static NMRP_REQ_CUSTOM reqConf = { NMRP_CODE_CONF_REQ, "CONF-REQ", "CONF-ACK", NMRPConfAckParser };
+
+ do {
+
+ ret = NMRPSend(&reqConf);
+ if( !ret)
+ {
+ cfe_sleep(CFE_HZ/2);
+ if(g_nmrp_config_acked)
+ {
+ break;
+ }
+ }
+
+ //}while(++retries <= NMRP_MAX_RETRY_CLOSE);
+ } while(1);
+
+ if(g_nmrp_config_acked)
+ {
+ devIp = NMRP_MsgGetOpt(&g_nmrpMsg, NMRP_OPT_DEV_IP);
+ *ipAddr = (* (DWORD *) devIp->value.streamVal);
+ *ipSubnetMask = (* (DWORD *) (devIp->value.streamVal + 4));
+ *fwUpgrade = NMRP_MsgGetOpt(&g_nmrpMsg, NMRP_OPT_FW_UP) != NULL;
+ return 0;
+ }
+ return -1;
+}
+
+static int NMRPSend(NMRP_REQ_CUSTOM *custom)
+{
+ ebuf_t *txbuf;
+ NMRP_MSG *msg;
+ unsigned long random_backoff;
+
+ txbuf = eth_alloc(netctx->ethinfo, g_portal_number);
+ if (!txbuf)
+ {
+ return -1;
+ }
+ msg = (NMRP_MSG *)(txbuf->eb_data + 14);
+ msg->reserved = 0;
+ msg->code = custom->reqCode;
+ msg->id = 0;
+ msg->length = HTONCS(NMRP_HDR_LEN); /* header only, no option */
+ txbuf->eb_length = NMRP_HDR_LEN;
+
+ random_backoff = rand();
+ random_backoff = random_backoff % 30;
+ xprintf("%s sent...Waiting for %s...\n", custom->reqName, custom->respName);
+ cfe_sleep(random_backoff);
+ eth_send(txbuf, (uint8_t *)g_NetInfo.peerMac);
+ eth_free(txbuf);
+
+ return 0;
+}
+
diff --git a/cfe/cfe/net/net_nmrp.h b/cfe/cfe/net/net_nmrp.h
new file mode 100755
index 0000000..052ff19
--- /dev/null
+++ b/cfe/cfe/net/net_nmrp.h
@@ -0,0 +1 @@
+int _start_nmrp(void);
diff --git a/cfe/cfe/net/net_tcp.c b/cfe/cfe/net/net_tcp.c
new file mode 100755
index 0000000..377c3c8
--- /dev/null
+++ b/cfe/cfe/net/net_tcp.c
@@ -0,0 +1,2215 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * TCP Protocol File: net_tcp.c
+ *
+ * This file contains a very simple TCP. The basic goals of this
+ * tcp are to be "good enough for firmware." We try to be
+ * correct in our protocol implementation, but not very fancy.
+ * In particular, we don't deal with out-of-order segments,
+ * we don't hesitate to copy data more then necessary, etc.
+ * We strive to implement important protocol features
+ * like slow start, nagle, etc., but even these things are
+ * subsetted and simplified as much as possible.
+ *
+ * Current "todo" list:
+ * slow start
+ * good testing of retransmissions,
+ * round-trip delay calculations
+ * Process received TCP options, particularly segment size
+ * Ignore urgent data (remove from datastream)
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+
+#include "net_ip.h"
+#include "net_ip_internal.h"
+
+#include "cfe_timer.h"
+
+#include "cfe_error.h"
+
+#include "net_tcpbuf.h"
+#include "net_tcp_internal.h"
+#include "net_tcp.h"
+
+/* *********************************************************************
+ * Config
+ ********************************************************************* */
+
+//#define _TCP_DEBUG_
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+struct tcp_info_s {
+ void *ti_ref; /* ref data for IP layer */
+ ip_info_t *ti_ipinfo; /* IP layer handle */
+ cfe_timer_t ti_fasttimer; /* 200ms timer */
+ queue_t ti_tcblist; /* list of known TCBs */
+ int ti_onqueue; /* number of TCBs on queue */
+ uint32_t ti_iss; /* initial sequence number */
+ tcb_t *ti_ports[TCP_MAX_PORTS]; /* table of active sockets */
+};
+
+/* *********************************************************************
+ * Forward Declarations
+ ********************************************************************* */
+
+static void _tcp_protosend(tcp_info_t *ti,tcb_t *tcb);
+static int _tcp_rx_callback(void *ref,ebuf_t *buf,uint8_t *destaddr,uint8_t *srcaddr);
+static void _tcp_output(tcp_info_t *ti,tcb_t *tcb);
+static void _tcp_aborttcb(tcp_info_t *ti,tcb_t *tcb);
+static void _tcp_closetcb(tcp_info_t *ti,tcb_t *tcb);
+static tcb_t *_tcp_find_lclport(tcp_info_t *ti,uint16_t port);
+static void _tcp_freetcb(tcp_info_t *ti,tcb_t *tcb);
+static void _tcp_sendctlmsg(tcp_info_t *ti,tcb_t *tcb,uint16_t flags,int timeout);
+
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#ifdef _TCP_DEBUG_
+#define _tcp_setstate(tcb,state) (tcb)->tcb_state = (state); \
+ printf("tcp state = " #state "\n");
+#define DEBUGMSG(x) printf x
+#else
+#define _tcp_setstate(tcb,state) (tcb)->tcb_state = (state);
+#define DEBUGMSG(x)
+#endif
+
+#define _tcp_preparectlmsg(tcb,flags) (tcb)->tcb_txflags = (flags) ; \
+ (tcb)->tcb_flags |= TCB_FLG_SENDMSG;
+
+#define _tcp_canceltimers(tcb) \
+ TIMER_CLEAR((tcb)->tcb_timer_retx); \
+ TIMER_CLEAR((tcb)->tcb_timer_keep); \
+ TIMER_CLEAR((tcb)->tcb_timer_2msl); \
+ TIMER_CLEAR((tcb)->tcb_timer_pers);
+
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+#ifdef _TCP_DEBUG_
+int _tcp_dumpflags = 1;
+#else
+int _tcp_dumpflags = 0;
+#endif
+
+/* *********************************************************************
+ * _tcp_init(ipi,ref)
+ *
+ * Initialize the TCP module. We set up our data structures
+ * and register ourselves with the IP layer.
+ *
+ * Input parameters:
+ * ipi - IP information
+ * ref - will be passed back to IP as needed
+ *
+ * Return value:
+ * tcp_info_t structure, or NULL if problems
+ ********************************************************************* */
+
+tcp_info_t *_tcp_init(ip_info_t *ipi,void *ref)
+{
+ tcp_info_t *ti;
+ int idx;
+
+ ti = (tcp_info_t *) KMALLOC(sizeof(tcp_info_t),0);
+ if (!ti) return NULL;
+
+ ti->ti_ref = ref;
+ ti->ti_ipinfo = ipi;
+
+ /*
+ * Start the "fast" timer
+ */
+
+ TIMER_SET(ti->ti_fasttimer,TCP_FAST_TIMER);
+
+ /*
+ * Initialize the TCB list
+ */
+
+ q_init(&(ti->ti_tcblist));
+
+ for (idx = 0; idx < TCP_MAX_PORTS; idx++) {
+ ti->ti_ports[idx] = NULL;
+ }
+
+ ti->ti_onqueue = 0;
+
+ /*
+ * Set up the initial sequence number
+ */
+
+ extern int32_t _getticks(void); /* return value of CP0 COUNT */
+ ti->ti_iss = (uint32_t) _getticks(); /* XXX nonportable */
+
+ /*
+ * Register our protocol with IP
+ */
+
+ _ip_register(ipi,IPPROTO_TCP,_tcp_rx_callback,ti);
+
+ return ti;
+}
+
+
+/* *********************************************************************
+ * _tcp_uninit(info)
+ *
+ * De-initialize the TCP layer, unregistering from the IP layer.
+ *
+ * Input parameters:
+ * info - our tcp_info_t, from _tcp_init()
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void _tcp_uninit(tcp_info_t *info)
+{
+ tcb_t *tcb;
+
+ /*
+ * Destroy all allocated TCBs, forcefully.
+ */
+
+ while (!q_isempty(&(info->ti_tcblist))) {
+ tcb = (tcb_t *) q_getfirst(&(info->ti_tcblist));
+ /* tcp_freetcb removes tcb from the queue */
+ _tcp_freetcb(info,tcb);
+ }
+
+ /*
+ * Deregister with IP
+ */
+
+ _ip_deregister(info->ti_ipinfo,IPPROTO_TCP);
+
+ /*
+ * Free up the info structure
+ */
+
+ KFREE(info);
+}
+
+
+/* *********************************************************************
+ * _tcp_freetcb(ti,tcb)
+ *
+ * Called when the TIME_WAIT timer expires, we use this to
+ * free up the TCB for good.
+ *
+ * Input parameters:
+ * ti - tcp information
+ * tcb - tcb to free
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void _tcp_freetcb(tcp_info_t *ti,tcb_t *tcb)
+{
+ /*
+ * Undo socket number
+ */
+
+ if (tcb->tcb_socknum >= 0) ti->ti_ports[tcb->tcb_socknum] = NULL;
+ tcb->tcb_socknum = -1;
+
+ /*
+ * Remove from queue
+ */
+
+ ti->ti_onqueue--;
+ q_dequeue(&(tcb->tcb_qb));
+
+ /*
+ * Free buffers (could probably be done in tcb_destroy)
+ */
+
+ tmb_free(&(tcb->tcb_txbuf));
+ tmb_free(&(tcb->tcb_rxbuf));
+
+ /*
+ * Free the TCB
+ */
+
+ KFREE(tcb);
+
+}
+
+/* *********************************************************************
+ * _tcp_socket(info)
+ *
+ * Create a new tcp socket (a new tcb structure is allocated
+ * and entered into the socket table)
+ *
+ * Input parameters:
+ * info - tcp information
+ *
+ * Return value:
+ * new socket number, or <0 if an error occured
+ ********************************************************************* */
+
+int _tcp_socket(tcp_info_t *info)
+{
+ int idx;
+ tcb_t *tcb;
+
+ /*
+ * Find an empty slot.
+ */
+
+ for (idx = 0; idx < TCP_MAX_PORTS; idx++) {
+ if (!info->ti_ports[idx]) break;
+ }
+
+ if (idx == TCP_MAX_PORTS) {
+ return CFE_ERR_NOHANDLES;
+ }
+
+ /*
+ * See if we can create another TCB
+ */
+
+ if (info->ti_onqueue >= TCP_MAX_TCBS) return CFE_ERR_NOMEM;
+
+ /*
+ * Allocate data structures
+ */
+
+ tcb = KMALLOC(sizeof(tcb_t),0);
+ if (!tcb) return CFE_ERR_NOMEM;
+
+ memset(tcb,0,sizeof(tcb_t));
+
+ if (tmb_alloc(&tcb->tcb_txbuf,TCP_BUF_SIZE) < 0) goto error;
+ if (tmb_alloc(&tcb->tcb_rxbuf,TCP_BUF_SIZE) < 0) goto error;
+
+ /*
+ * XXX Temp: our MTU is always 1400. We could/should
+ * XXX get this from the lower layer.
+ */
+
+ tcb->tcb_mtu = 1400;
+
+ /*
+ * Default socket flags
+ */
+
+ tcb->tcb_sockflags = TCPFLG_NBIO;
+
+ /*
+ * Set up initial state. Find an empty port number.
+ * note that the way we do this is pretty gruesome, but it will
+ * work for our small TCP, where the number of TCBs outstanding
+ * will be very small compared to the port number space.
+ *
+ * Try to look up the port number we want - if we find it, increment
+ * it and try again until we find an unused one.
+ * Stay away from ports 0..1023.
+ */
+
+ _tcp_setstate(tcb,TCPSTATE_CLOSED);
+ tcb->tcb_lclport = (uint16_t) (((uint16_t) cfe_ticks) + 1024);
+
+ while (_tcp_find_lclport(info,tcb->tcb_lclport) != NULL) {
+ tcb->tcb_lclport++;
+ if (tcb->tcb_lclport == 0) tcb->tcb_lclport = 1024;
+ }
+
+ /*
+ * Remember this socket in the table
+ */
+
+ info->ti_ports[idx] = tcb;
+ tcb->tcb_socknum = idx;
+
+ info->ti_onqueue++;
+ q_enqueue(&(info->ti_tcblist),&(tcb->tcb_qb));
+
+ return idx;
+
+error:
+ tmb_free(&(tcb->tcb_txbuf));
+ tmb_free(&(tcb->tcb_rxbuf));
+ KFREE(tcb);
+ return CFE_ERR_NOMEM;
+}
+
+
+/* *********************************************************************
+ * _tcp_connect(ti,s,dest,port)
+ *
+ * Connect a socket to a remote port.
+ *
+ * Input parameters:
+ * ti - TCP information
+ * s - socket number, allocated via _tcp_create
+ * dest - destination IP address
+ * port - destination port number
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int _tcp_connect(tcp_info_t *ti,int s,uint8_t *dest,uint16_t port)
+{
+ tcb_t *tcb;
+
+ tcb = ti->ti_ports[s];
+ if (!tcb) return CFE_ERR_INV_PARAM;
+
+ memcpy(tcb->tcb_peeraddr,dest,IP_ADDR_LEN);
+ tcb->tcb_peerport = port;
+
+ tcb->tcb_rcvnext = 0;
+ tcb->tcb_rcvack = 0;
+
+ tcb->tcb_sendnext = ti->ti_iss;
+ tcb->tcb_sendunack = ti->ti_iss;
+ tcb->tcb_sendwindow = 0;
+
+ tmb_init(&tcb->tcb_txbuf);
+ tmb_init(&tcb->tcb_rxbuf);
+
+ TIMER_SET(tcb->tcb_timer_keep,TCP_KEEPALIVE_TIMER);
+ _tcp_setstate(tcb,TCPSTATE_SYN_SENT);
+
+ _tcp_sendctlmsg(ti,tcb,TCPFLG_SYN,TCP_RETX_TIMER);
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * _tcp_close(ti,s)
+ *
+ * Disconnect a TCP socket nicely. Sends a FIN packet to get
+ * us into the disconnect state.
+ *
+ * Input parameters:
+ * ti - tcp information
+ * s - socket number
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int _tcp_close(tcp_info_t *ti,int s)
+{
+ tcb_t *tcb;
+
+ tcb = ti->ti_ports[s];
+ if (!tcb) return CFE_ERR_INV_PARAM;
+
+#if defined(CONFIG_MIPS_BRCM)
+ /*
+ * Flush output data.
+ */
+
+ _tcp_output(ti,tcb);
+#endif
+
+ /*
+ * Reclaim this socket number for future use
+ */
+
+ ti->ti_ports[s] = NULL;
+ tcb->tcb_socknum = -1;
+
+ /*
+ * Decide what action to take based on current state
+ */
+
+ switch (tcb->tcb_state) {
+ case TCPSTATE_SYN_RECEIVED:
+ case TCPSTATE_ESTABLISHED:
+ /*
+ * Transmit the FIN/ACK and wait for a FIN/ACK.
+ *
+ * XXX probably want to wait till all unacked data is
+ * acked before sending the fin?? This would be sort
+ * of like the "linger" option
+ */
+ _tcp_setstate(tcb,TCPSTATE_FINWAIT_1);
+ _tcp_sendctlmsg(ti,tcb,TCPFLG_ACK | TCPFLG_FIN,TCP_RETX_TIMER);
+ break;
+
+ case TCPSTATE_CLOSED:
+ case TCPSTATE_LISTEN:
+ case TCPSTATE_SYN_SENT:
+ /*
+ * Disconnect during our attempt, or from some
+ * idle state that does not require sending anything.
+ * Go back to CLOSED.
+ */
+ _tcp_closetcb(ti,tcb);
+ _tcp_freetcb(ti,tcb);
+ break;
+
+ case TCPSTATE_CLOSE_WAIT:
+ _tcp_setstate(tcb,TCPSTATE_LAST_ACK);
+ _tcp_sendctlmsg(ti,tcb,TCPFLG_ACK | TCPFLG_FIN,TCP_RETX_TIMER);
+ break;
+
+ case TCPSTATE_TIME_WAIT:
+ case TCPSTATE_FINWAIT_1:
+ case TCPSTATE_FINWAIT_2:
+ case TCPSTATE_CLOSING:
+ case TCPSTATE_LAST_ACK:
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+
+/* *********************************************************************
+ * _tcp_aborttcb(ti,tcb)
+ *
+ * Forcefully terminate a TCP connection. Sends an RST packet
+ * to nuke the other end. The socket is forced into the CLOSED
+ * state.
+ *
+ * Input parameters:
+ * ti - tcp information
+ * tcb -tcb to abort
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void _tcp_aborttcb(tcp_info_t *ti,tcb_t *tcb)
+{
+ DEBUGMSG(("tcp_abort from state %d\n",tcb->tcb_state));
+
+ /*
+ * Decide what action to take based on current state
+ * If we're in SYN_SENT, RECEIVED, ESTABLISHED, FINWAIT_1,
+ * FINWAIT_2, CLOSING, LAST_ACK, or CLOSE_WAIT we've sent
+ * some traffic on this TCB, so send an RST to kill off
+ * the remote TCB.
+ */
+
+ if (TCPSTATE_IN_SET(tcb->tcb_state,M_TCPSTATE_ABORTSTATES)) {
+ /* Send RST with no timeout, don't retransmit it. */
+ _tcp_canceltimers(tcb);
+ _tcp_sendctlmsg(ti,tcb,TCPFLG_ACK | TCPFLG_RST,0);
+ }
+
+ /*
+ * No matter what, it's now CLOSED.
+ */
+
+ _tcp_closetcb(ti,tcb);
+
+}
+
+
+/* *********************************************************************
+ * _tcp_closetcb(ti,tcb)
+ *
+ * Close a TCB, switching the state to "closed" and resetting
+ * internal variables. The TCB is *not* freed.
+ *
+ * Input parameters:
+ * ti - tcp information
+ * tcb - tcb to close
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void _tcp_closetcb(tcp_info_t *ti,tcb_t *tcb)
+{
+ /*
+ * Set state to "closed" and reset timers
+ */
+
+ _tcp_setstate(tcb,TCPSTATE_CLOSED);
+ tcb->tcb_flags = 0;
+ _tcp_canceltimers(tcb);
+
+ /*
+ * Reinitialize the buffers to waste the stored send data and
+ * clear out any receive data
+ */
+
+ tmb_init(&tcb->tcb_txbuf);
+ tmb_init(&tcb->tcb_rxbuf);
+}
+
+/* *********************************************************************
+ * _tcp_send(ti,s,buf,len)
+ *
+ * Queue some data to be transmitted via a TCP socket
+ *
+ * Input parameters:
+ * ti - TCP information
+ * s - socket number
+ * buf - buffer of data to send
+ * len - size of buffer to send
+ *
+ * Return value:
+ * number of bytes queued
+ * <0 if an error occured
+ ********************************************************************* */
+
+int _tcp_send(tcp_info_t *ti,int s,uint8_t *buf,int len)
+{
+ tcb_t *tcb;
+ int retlen;
+ int curlen;
+
+ tcb = ti->ti_ports[s];
+ if (!tcb) return CFE_ERR_INV_PARAM;
+
+ /*
+ * State must be ESTABLISHED or CLOSE_WAIT. CLOSE_WAIT
+ * means we've received a fin, but we can still send in
+ * the outbound direction.
+ */
+
+ if (!TCPSTATE_IN_SET(tcb->tcb_state,M_TCPSTATE_SEND_OK)) {
+ return CFE_ERR_NOTCONN;
+ }
+
+ /*
+ * Copy the user data into the transmit buffer.
+ */
+
+ curlen = tmb_curlen(&(tcb->tcb_txbuf));
+ retlen = tmb_copyin(&(tcb->tcb_txbuf),buf,len,TRUE);
+
+ /*
+ * Cause some output on the device.
+ */
+
+ /*
+ * Nagle: Call _tcp_output only if there is no outstanding
+ * unacknowledged data. The way our transmit buffer
+ * works, it only holds unacknowledged data, so this
+ * test is easy. It isn't really 100% correct to
+ * do it this way, but the effect is the same; we will
+ * not transmit tinygrams.
+ */
+
+ if ((curlen == 0) || (tcb->tcb_sockflags & TCPFLG_NODELAY)) {
+ _tcp_output(ti,tcb);
+ }
+
+ return retlen;
+}
+
+/* *********************************************************************
+ * _tcp_recv(ti,s,buf,len)
+ *
+ * Get buffered receive data from the TCP socket
+ *
+ * Input parameters:
+ * ti - tcp information
+ * s - socket number
+ * buf - pointer to receive buffer area
+ * len - size of receive buffer area
+ *
+ * Return value:
+ * number of bytes received
+ * <0 if an error occured
+ * ==0 if no data available (or tcp session is closed)
+ ********************************************************************* */
+
+int _tcp_recv(tcp_info_t *ti,int s,uint8_t *buf,int len)
+{
+ tcb_t *tcb;
+ int retlen;
+
+ tcb = ti->ti_ports[s];
+ if (!tcb) return CFE_ERR_INV_PARAM;
+
+ if (!TCPSTATE_IN_SET(tcb->tcb_state,M_TCPSTATE_RECV_OK)) {
+ return CFE_ERR_NOTCONN;
+ }
+
+ retlen = tmb_copyout(&(tcb->tcb_rxbuf),buf,len,TRUE);
+
+ /*
+ * If we've drained all of the data out of the buffer
+ * send an ack. This isn't ideal, but it will
+ * prevent us from keeping the window closed.
+ */
+
+// if (retlen && (tmb_curlen(&(tcb->tcb_rxbuf)) == 0)) {
+// _tcp_preparectlmsg(tcb,TCPFLG_ACK);
+// _tcp_protosend(ti,tcb);
+// tcb->tcb_flags &= ~TCB_FLG_DLYACK;
+// }
+
+ return retlen;
+}
+
+
+/* *********************************************************************
+ * _tcp_bind(ti,s,port)
+ *
+ * "bind" a TCP socket to a particular port - this sets the
+ * outbound local (source) port number.
+ *
+ * Input parameters:
+ * ti - tcp information
+ * s - socket number
+ * port - port number
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int _tcp_bind(tcp_info_t *ti,int s,uint16_t port)
+{
+ tcb_t *tcb;
+
+ tcb = ti->ti_ports[s];
+ if (!tcb) return CFE_ERR_INV_PARAM;
+
+ /* XXX test state - must be in 'closed' */
+
+ if (_tcp_find_lclport(ti,port)) return CFE_ERR_ADDRINUSE;
+
+ tcb->tcb_lclport = port;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * _tcp_setflags(ti,s,flags)
+ *
+ * Set per-socket flags.
+ *
+ * Input parameters:
+ * ti - tcp information
+ * s - socket number
+ * flags - flags to set
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int _tcp_setflags(tcp_info_t *ti,int s,unsigned int flags)
+{
+ tcb_t *tcb;
+
+ tcb = ti->ti_ports[s];
+ if (!tcb) return CFE_ERR_INV_PARAM;
+
+ tcb->tcb_sockflags = flags;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * _tcp_getflags(ti,s,flags)
+ *
+ * Get per-socket flags.
+ *
+ * Input parameters:
+ * ti - tcp information
+ * s - socket number
+ * flags - pointer to int to receive flags
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int _tcp_getflags(tcp_info_t *ti,int s,unsigned int *flags)
+{
+ tcb_t *tcb;
+
+ tcb = ti->ti_ports[s];
+ if (!tcb) return CFE_ERR_INV_PARAM;
+
+ *flags = tcb->tcb_sockflags;
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * _tcp_peeraddr(ti,s,addr,port)
+ *
+ * Return the address of the computer on the other end of this
+ * connection.
+ *
+ * Input parameters:
+ * ti - tcp information
+ * s - socket number
+ * addr - receives IP address of remote
+ * port - port number
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int _tcp_peeraddr(tcp_info_t *ti,int s,uint8_t *addr,uint16_t *port)
+{
+ tcb_t *tcb;
+
+ tcb = ti->ti_ports[s];
+ if (!tcb) return CFE_ERR_INV_PARAM;
+
+ /*
+ * Test for any of the states where we believe the peeraddr in the tcb
+ * is valid.
+ */
+
+ if (!TCPSTATE_IN_SET(tcb->tcb_state,M_TCPSTATE_PEERADDR_OK)) {
+ return CFE_ERR_NOTCONN;
+ }
+
+ if (addr) memcpy(addr,tcb->tcb_peeraddr,IP_ADDR_LEN);
+ if (port) *port = tcb->tcb_peerport;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * _tcp_listen(ti,s,port)
+ *
+ * Set a socket for listening mode, allowing inbound connections
+ * to occur.
+ *
+ * Input parameters:
+ * ti - tcp information
+ * s - socket nunber
+ * port - port number to listen for (implicit tcp_bind)
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int _tcp_listen(tcp_info_t *ti,int s,uint16_t port)
+{
+ tcb_t *tcb;
+ queue_t *qb;
+
+ /*
+ * See if another TCB is listening to this port
+ */
+
+ for (qb = ti->ti_tcblist.q_next; qb != &(ti->ti_tcblist); qb = qb->q_next) {
+ tcb = (tcb_t *) qb;
+
+ if ((tcb->tcb_lclport == port) &&
+ (tcb->tcb_state == TCPSTATE_LISTEN) &&
+ (tcb->tcb_peerport == 0)) return CFE_ERR_ADDRINUSE;
+
+ }
+
+ /*
+ * Otherwise, we're good to go.
+ */
+
+ tcb = ti->ti_ports[s];
+ if (!tcb) return CFE_ERR_INV_PARAM;
+
+ tcb->tcb_lclport = port;
+ _tcp_setstate(tcb,TCPSTATE_LISTEN);
+
+ tcb->tcb_sendnext = 0;
+ tcb->tcb_sendunack = 0;
+ tcb->tcb_sendwindow = 0;
+ _tcp_canceltimers(tcb);
+
+ tcb->tcb_rcvnext = 0;
+ tcb->tcb_rcvack = 0;
+
+ tmb_init(&tcb->tcb_txbuf);
+ tmb_init(&tcb->tcb_rxbuf);
+
+ tcb->tcb_txflags = 0;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * _tcp_status(ti,s,connflag,rxready,rxeof)
+ *
+ * Get status information about the TCP session
+ *
+ * Input parameters:
+ * ti - tcp information
+ * s - socket nunber
+ * connflag - points to an int to receive connection status
+ * (1=connected,0=not connected)
+ * rxready - number of bytes in receive queue
+ * rxeof - returns 1 if we've been FINed.
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int _tcp_status(tcp_info_t *ti,int s,unsigned int *connflag,int *rxready,int *rxeof)
+{
+ tcb_t *tcb;
+ int rxlen;
+
+ tcb = ti->ti_ports[s];
+ if (!tcb) return CFE_ERR_INV_PARAM;
+
+ rxlen = tmb_curlen(&(tcb->tcb_rxbuf));
+
+ /*
+ * We consider the connection "connected" if it's established
+ * or it's in CLOSE_WAIT (FIN received) but we have not drained
+ * all of the receive data.
+ *
+ * Otherwise: If it's not in one of the connection establishment states,
+ * it's not connected.
+ */
+
+ if (connflag) {
+ if ((tcb->tcb_state == TCPSTATE_ESTABLISHED) ||
+ ((rxlen != 0) && (tcb->tcb_state == TCPSTATE_CLOSE_WAIT))) {
+ *connflag = TCPSTATUS_CONNECTED;
+ }
+ else if (TCPSTATE_IN_SET(tcb->tcb_state,M_TCPSTATE_CONNINPROGRESS)) {
+ *connflag = TCPSTATUS_CONNECTING;
+ }
+ else {
+ *connflag = TCPSTATUS_NOTCONN;
+ }
+ }
+
+ if (rxready) {
+ *rxready = rxlen;
+ }
+
+ if (rxeof) {
+ *rxeof = 0;
+ if ((tcb->tcb_state == TCPSTATE_CLOSE_WAIT) ||
+ (tcb->tcb_state == TCPSTATE_LAST_ACK)) {
+ *rxeof = 1;
+ }
+ }
+
+ return 0;
+}
+
+/* *********************************************************************
+ * _tcp_debug(ti,s,arg)
+ *
+ * Perform debug functions on a socket
+ *
+ * Input parameters:
+ * ti - tcp information
+ * s - socket number
+ * arg - argument
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int _tcp_debug(tcp_info_t *ti,int s,int arg)
+{
+ tcb_t *tcb;
+
+ tcb = ti->ti_ports[s];
+ if (!tcb) return CFE_ERR_INV_PARAM;
+
+ printf("State=%d SendNext=%u SendUnack=%u ",
+ tcb->tcb_state,tcb->tcb_sendnext,tcb->tcb_sendunack);
+ printf("SendWin=%d Ack=%u Rxlen=%d\n",
+ tcb->tcb_sendwindow,
+ tcb->tcb_rcvack,tmb_curlen(&(tcb->tcb_rxbuf)));
+
+ return 0;
+}
+
+
+#ifdef _TCP_DEBUG_
+/* *********************************************************************
+ * _tcp_dumppktstate(label,flags,ack,seq,len)
+ *
+ * A debug function.
+ *
+ * Input parameters:
+ * label - printed before packet state
+ * flags - transmit flags for packet
+ * ack,seq,len - from the packet
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void _tcp_dumppktstate(char *label,uint16_t flags,
+ uint32_t ack,uint32_t seq,int len)
+{
+ printf("%s: ",label);
+ if (flags & TCPFLG_FIN) printf("FIN ");
+ if (flags & TCPFLG_SYN) printf("SYN ");
+ if (flags & TCPFLG_RST) printf("RST ");
+ if (flags & TCPFLG_PSH) printf("PSH ");
+ if (flags & TCPFLG_ACK) printf("ACK ");
+ if (flags & TCPFLG_URG) printf("URG ");
+ printf("Ack=%u Seq=%u Data=%d\n",ack,seq,len);
+}
+#endif
+
+
+/* *********************************************************************
+ * _tcp_output(ti,tcb)
+ *
+ * Try to perform some output on this TCB. If there is
+ * data to send and we can transmit it (i.e., the remote's
+ * receive window will allow it), segment the data from the
+ * buffer and transmit it, updating local state variables.
+ *
+ * Input parameters:
+ * ti - tcp information
+ * tcb - the tcb to send data on
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void _tcp_output(tcp_info_t *ti,tcb_t *tcb)
+{
+ ebuf_t *b;
+ int tcplen;
+ int window;
+ uint16_t flags;
+ uint8_t *cksumptr;
+ uint8_t *tcphdr;
+ uint16_t cksum;
+ int hdrlen;
+ uint8_t pseudoheader[12];
+ int offset;
+ uint32_t sendmax;
+ uint32_t windowmax;
+ uint32_t cwndmax;
+
+ /*
+ * sendmax is (one plus) the highest sequence number we have
+ * data for.
+ *
+ * windowmax is (one plus) the highest sequence number in the
+ * send window.
+ *
+ * cwndmax is (one plus) the highest sequence number in the
+ * congestion window.
+ */
+
+ sendmax = tcb->tcb_sendunack + tmb_curlen(&(tcb->tcb_txbuf));
+ windowmax = tcb->tcb_sendunack + tcb->tcb_sendwindow;
+ cwndmax = tcb->tcb_sendunack + 5*1400;
+
+ /*
+ * We'll send up to 'sendmax', 'cwndmax', or 'windowmax' bytes, whichever
+ * is sooner. Set 'sendmax' to the earliest sequence number.
+ */
+
+ if (TCPSEQ_GT(sendmax,windowmax)) sendmax = windowmax;
+ if (TCPSEQ_GT(sendmax,cwndmax)) sendmax = cwndmax;
+
+ /*
+ * The (receive) window is whatever it takes to fill the buffer.
+ */
+
+ window = tmb_remlen(&(tcb->tcb_rxbuf));
+ if (window > 65000) window = 65000;
+
+ /*
+ * Spit out packets until "sendnext" either catches up
+ * or exceeds the remote window
+ */
+
+ while (TCPSEQ_LT(tcb->tcb_sendnext,sendmax)) {
+
+ /*
+ * This is the offset into the transmit buffer to start with.
+ * Offset 0 in the transmit buffer corresponds to "send unack"
+ * received acks move this pointer.
+ */
+
+ offset = tcb->tcb_sendnext - tcb->tcb_sendunack;
+
+ /*
+ * Allocate a buffer and remember the pointer to where
+ * the header starts.
+ */
+
+ b = _ip_alloc(ti->ti_ipinfo);
+ if (!b) break;
+
+ tcphdr = ebuf_ptr(b) + ebuf_length(b);
+
+ flags = TCPFLG_ACK | TCPHDRFLG(TCP_HDR_LENGTH);
+ hdrlen = TCP_HDR_LENGTH;
+
+ /*
+ * Fill in the fields according to the RFC.
+ */
+
+ tcb->tcb_rcvack = tcb->tcb_rcvnext; /* Update our "most recent ack" */
+
+ ebuf_append_u16_be(b,tcb->tcb_lclport); /* Local and remote ports */
+ ebuf_append_u16_be(b,tcb->tcb_peerport);
+ ebuf_append_u32_be(b,tcb->tcb_sendnext); /* sequence and ack numbers */
+ ebuf_append_u32_be(b,tcb->tcb_rcvack);
+ ebuf_append_u16_be(b,flags); /* Flags */
+ ebuf_append_u16_be(b,window); /* Window size */
+ cksumptr = ebuf_ptr(b) + ebuf_length(b);
+ ebuf_append_u16_be(b,0); /* dummy checksum for calculation */
+ ebuf_append_u16_be(b,0); /* Urgent Pointer (not used) */
+
+ /*
+ * Append the data, copying pieces out of the transmit buffer
+ * without adjusting its pointers.
+ */
+
+ tcplen = tmb_copyout2(&(tcb->tcb_txbuf),
+ b->eb_ptr + b->eb_length,
+ offset,
+ tcb->tcb_mtu);
+
+ b->eb_length += tcplen;
+
+#ifdef _TCP_DEBUG_
+ if (_tcp_dumpflags) _tcp_dumppktstate("TX_DATA",flags,
+ tcb->tcb_sendnext,
+ tcb->tcb_rcvack,tcplen);
+#endif
+
+ /*
+ * Adjust the "send next" sequence number to account for what
+ * we're about to send.
+ */
+
+ tcb->tcb_sendnext += tcplen;
+
+
+ /*
+ * Build the pseudoheader, which is part of the checksum calculation
+ */
+
+ _ip_getaddr(ti->ti_ipinfo,&pseudoheader[0]);
+ memcpy(&pseudoheader[4],tcb->tcb_peeraddr,IP_ADDR_LEN);
+ pseudoheader[8] = 0;
+ pseudoheader[9] = IPPROTO_TCP;
+ pseudoheader[10] = ((tcplen+hdrlen) >> 8) & 0xFF;
+ pseudoheader[11] = ((tcplen+hdrlen) & 0xFF);
+
+ /*
+ * Checksum the packet and insert the checksum into the header
+ */
+
+ cksum = ip_chksum(0,pseudoheader,sizeof(pseudoheader));
+ cksum = ip_chksum(cksum,tcphdr,tcplen + hdrlen);
+ cksum = ~cksum;
+ cksumptr[0] = (cksum >> 8) & 0xFF;
+ cksumptr[1] = (cksum & 0xFF);
+
+ /*
+ * Transmit the packet. The layer below us will free it.
+ */
+
+ _ip_send(ti->ti_ipinfo,b,tcb->tcb_peeraddr,IPPROTO_TCP);
+
+ /*
+ * Set the timer that we'll use to wait for an acknowledgement.
+ * If this timer goes off, we'll rewind "sendnext" back to
+ * "sendunack" and transmit stuff again.
+ */
+
+ TIMER_SET(tcb->tcb_timer_retx,TCP_RETX_TIMER);
+
+ /*
+ * We just sent an ack, so cancel the delayed ack timer.
+ */
+
+ tcb->tcb_flags &= ~TCB_FLG_DLYACK;
+
+ }
+
+}
+
+/* *********************************************************************
+ * _tcp_protosend(ti,tcb)
+ *
+ * Transmit "protocol messages" on the tcb. This is used for
+ * sending SYN, FIN, ACK, and other control packets.
+ *
+ * Input parameters:
+ * ti - tcp infomration
+ * tcb - tcb we're interested in
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void _tcp_protosend(tcp_info_t *ti,tcb_t *tcb)
+{
+ ebuf_t *b;
+ int tcplen;
+ int window;
+ uint16_t flags;
+ uint8_t *cksumptr;
+ uint8_t *tcphdr;
+ uint16_t cksum;
+ int hdrlen;
+ uint8_t pseudoheader[12];
+
+ /*
+ * Allocate a buffer and remember the pointer to where
+ * the header starts.
+ */
+
+ b = _ip_alloc(ti->ti_ipinfo);
+ if (!b) return;
+
+ tcphdr = ebuf_ptr(b) + ebuf_length(b);
+
+ /*
+ * We're going to send something, so we can clear the flag.
+ * Also clear the delay-ack flag since everything's an ack.
+ */
+
+ tcb->tcb_flags &= ~(TCB_FLG_SENDMSG | TCB_FLG_DLYACK);
+
+ /*
+ * Build the TCP header
+ */
+
+ /* The flags are the current flags + the header length */
+ if (tcb->tcb_txflags & TCPFLG_SYN) {
+ flags = tcb->tcb_txflags | (TCPHDRFLG(TCP_HDR_LENGTH + 4));
+ hdrlen = TCP_HDR_LENGTH + 4;
+ }
+ else {
+ flags = tcb->tcb_txflags | (TCPHDRFLG(TCP_HDR_LENGTH));
+ hdrlen = TCP_HDR_LENGTH;
+ }
+
+
+#ifdef _TCP_DEBUG_
+ if (_tcp_dumpflags) _tcp_dumppktstate("TX_CTL",flags,
+ tcb->tcb_sendnext,
+ tcb->tcb_rcvack,0);
+#endif
+
+ /*
+ * The (receive) window is whatever it takes to fill the buffer.
+ */
+
+ window = tmb_remlen(&(tcb->tcb_rxbuf));
+ if (window > 65000) window = 65000;
+
+ /*
+ * Fill in the fields according to the RFC.
+ */
+
+ tcb->tcb_rcvack = tcb->tcb_rcvnext; /* update last tx ack */
+
+ ebuf_append_u16_be(b,tcb->tcb_lclport); /* Local and remote ports */
+ ebuf_append_u16_be(b,tcb->tcb_peerport);
+ ebuf_append_u32_be(b,tcb->tcb_sendnext); /* sequence and ack numbers */
+ ebuf_append_u32_be(b,tcb->tcb_rcvack);
+ ebuf_append_u16_be(b,flags); /* Flags */
+ ebuf_append_u16_be(b,window); /* Window size */
+ cksumptr = ebuf_ptr(b) + ebuf_length(b);
+ ebuf_append_u16_be(b,0); /* dummy checksum for calculation */
+ ebuf_append_u16_be(b,0); /* Urgent Pointer (not used) */
+
+ /*
+ * Append TCP options on SYN packet
+ */
+
+ if (flags & TCPFLG_SYN) {
+ ebuf_append_u16_be(b,TCP_MAX_SEG_OPT);
+ ebuf_append_u16_be(b,TCP_MAX_SEG_SIZE);
+ }
+
+ tcplen = 0; /* don't transmit data here */
+
+ /*
+ * SYN and FIN packets consume a sequence number, so
+ * increment the "sendnext" variable. If we need to retransmit
+ * these segments, we'll wind "sendnext" back to "sendunack"
+ *
+ * XXX: Can you send a SYN and FIN at the same time?
+ */
+
+ if (flags & (TCPFLG_SYN | TCPFLG_FIN)) tcb->tcb_sendnext++;
+
+ /*
+ * Build the pseudoheader, which is part of the checksum calculation
+ */
+
+ _ip_getaddr(ti->ti_ipinfo,&pseudoheader[0]);
+ memcpy(&pseudoheader[4],tcb->tcb_peeraddr,IP_ADDR_LEN);
+ pseudoheader[8] = 0;
+ pseudoheader[9] = IPPROTO_TCP;
+ pseudoheader[10] = ((tcplen+hdrlen) >> 8) & 0xFF;
+ pseudoheader[11] = ((tcplen+hdrlen) & 0xFF);
+
+ /*
+ * Checksum the packet and insert the checksum into the header
+ */
+
+ cksum = ip_chksum(0,pseudoheader,sizeof(pseudoheader));
+ cksum = ip_chksum(cksum,tcphdr,tcplen + hdrlen);
+ cksum = ~cksum;
+ cksumptr[0] = (cksum >> 8) & 0xFF;
+ cksumptr[1] = (cksum & 0xFF);
+
+ /*
+ * Transmit the packet. The layer below us will free it.
+ */
+
+ _ip_send(ti->ti_ipinfo,b,tcb->tcb_peeraddr,IPPROTO_TCP);
+}
+
+/* *********************************************************************
+ * _tcp_sendreset(ti,dstipaddr,ack,srcport,dstport)
+ *
+ * Transmit "protocol messages" on the tcb. This is used for
+ * sending SYN, FIN, ACK, and other control packets.
+ *
+ * Input parameters:
+ * ti - tcp infomration
+ * tcb - tcb we're interested in
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void _tcp_sendreset(tcp_info_t *ti,uint8_t *dstipaddr,uint32_t ack,
+ uint16_t srcport,uint16_t dstport)
+{
+ tcb_t tcb; /* fake TCB so we can use _tcp_protosend */
+
+ memset(&tcb,0,sizeof(tcb));
+ memcpy(tcb.tcb_peeraddr,dstipaddr,IP_ADDR_LEN);
+ tcb.tcb_peerport = dstport;
+ tcb.tcb_lclport = srcport;
+ tcb.tcb_txflags = TCPFLG_RST|TCPFLG_ACK;
+ tcb.tcb_rcvnext = ack;
+
+ _tcp_protosend(ti,&tcb);
+}
+
+
+/* *********************************************************************
+ * _tcp_sendctlmsg(ti,tcb,flags,timeout)
+ *
+ * Set up for and transmit a control message. This is usually
+ * called on a state transition where we need to send a control
+ * message like a SYN or FIN, with a timeout. We reset the
+ * retry counter, set the retransmit timer, and fire off the message
+ * right here.
+ *
+ * Input parameters:
+ * ti - tcp information
+ * tcb - the tcb for this TCP session
+ * flags - packet flags (TCPFLG_xxx)
+ * timeout - timeout value , in ticks
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void _tcp_sendctlmsg(tcp_info_t *ti,tcb_t *tcb,uint16_t flags,int timeout)
+{
+ tcb->tcb_txflags = flags;
+ tcb->tcb_retrycnt = 0;
+
+ if (timeout >= 0) {
+ if (timeout) {
+ TIMER_SET(tcb->tcb_timer_retx,timeout);
+ }
+ else {
+ TIMER_CLEAR(tcb->tcb_timer_retx);
+ }
+ }
+
+ _tcp_protosend(ti,tcb);
+}
+
+
+/* *********************************************************************
+ * _tcp_find_lclport(ti,port)
+ *
+ * Find the specified local port - mostly to see if it is
+ * already in use.
+ *
+ * Input parameters:
+ * ti - tcp information
+ * port - local port
+ *
+ * Return value:
+ * tcb owning this port, or NULL if none found
+ ********************************************************************* */
+static tcb_t *_tcp_find_lclport(tcp_info_t *ti,uint16_t port)
+{
+ tcb_t *tcb = NULL;
+ queue_t *qb;
+
+ for (qb = ti->ti_tcblist.q_next; qb != &(ti->ti_tcblist); qb = qb->q_next) {
+ tcb = (tcb_t *) qb;
+
+ if (tcb->tcb_lclport == port) return tcb;
+
+ }
+
+ return NULL;
+
+}
+
+/* *********************************************************************
+ * _tcp_find_tcb(ti,srcport,dstport,saddr)
+ *
+ * Locate the TCB in the active TCBs. This is used to match
+ * an inbound TCP packet to a TCB.
+ *
+ * Input parameters:
+ * ti - tcp information
+ * srcport,dstport - source and dest ports from TCP header
+ * saddr - source IP address of sending host
+ *
+ * Return value:
+ * tcb pointer or NULL if no TCB was found
+ ********************************************************************* */
+
+static tcb_t *_tcp_find_tcb(tcp_info_t *ti,uint16_t srcport,uint16_t dstport,uint8_t *saddr)
+{
+ tcb_t *tcb = NULL;
+ queue_t *qb;
+
+ for (qb = ti->ti_tcblist.q_next; qb != &(ti->ti_tcblist); qb = qb->q_next) {
+ tcb = (tcb_t *) qb;
+
+ /* Try active TCBs */
+ if ((tcb->tcb_peerport != 0) &&
+ (tcb->tcb_lclport == dstport) &&
+ (tcb->tcb_peerport == srcport) &&
+ (memcmp(saddr,tcb->tcb_peeraddr,IP_ADDR_LEN) == 0)) break;
+ }
+
+ /* Found it on our active list. */
+ if (qb != &(ti->ti_tcblist)) return tcb;
+
+ /* no dice, try listening ports */
+ for (qb = ti->ti_tcblist.q_next; qb != &(ti->ti_tcblist); qb = qb->q_next) {
+ tcb = (tcb_t *) qb;
+
+ /* Try active TCBs */
+ if ((tcb->tcb_peerport == 0) &&
+ (tcb->tcb_lclport == dstport)) break;
+ }
+
+ /* Found it on our passive list. */
+ if (qb != &(ti->ti_tcblist)) return tcb;
+
+ return NULL;
+}
+
+/* *********************************************************************
+ * _tcp_procack(ti,tcb,ack,flags)
+ *
+ * Process a received acknowledgement.
+ *
+ * Input parameters:
+ * ti - tcp information
+ * tcb - tcb for this tcb session
+ * ack - acknum from received packet
+ * flags - flags from received packet
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void _tcp_procack(tcp_info_t *ti,tcb_t *tcb,uint32_t ack,uint16_t flags)
+{
+ int ackamt;
+ int unacklen;
+
+ /* This is the number of unacknowledged bytes we have */
+ unacklen = tmb_curlen(&(tcb->tcb_txbuf));
+
+ switch (tcb->tcb_state) {
+
+ case TCPSTATE_ESTABLISHED:
+ /*
+ * The ack is valid if it's in the range of
+ * unacknowledged data we're holding onto.
+ *
+ * sendunack < ack <= (sendunack+datalen)
+ *
+ * Do the first comparison as "<=" instead of just "<"
+ * so we can catch duplicate acks.
+ */
+
+ if (!(TCPSEQ_LEQ(tcb->tcb_sendunack,ack) &&
+ TCPSEQ_LEQ(ack,(tcb->tcb_sendunack+unacklen)))) {
+ DEBUGMSG(("Ack is out of range: %u\n",ack));
+ return;
+ }
+
+ /*
+ * Compute the # of bytes spanned by this ack
+ */
+
+ ackamt = TCPSEQ_DIFF(ack,tcb->tcb_sendunack);
+
+ /*
+ * If we actually acked something, adjust the tx buffer
+ * to remove the bytes covered by the ack, then update
+ * the 'next' sequence number so we'll start there next
+ * time.
+ */
+
+ if (ackamt > 0) {
+ tmb_adjust(&tcb->tcb_txbuf,ackamt);
+ tcb->tcb_txflags = TCPFLG_ACK;
+ tcb->tcb_sendunack = ack;
+ tcb->tcb_dup_ackcnt = 0; /* not a duplicate */
+ }
+ else {
+ tcb->tcb_dup_ackcnt++;
+ //DEBUGMSG(("Duplicate ack received\n"));
+ /*
+ * Duplicate ack received
+ * XXX This is where we'd be doing stuff for
+ * XXX slow-start, fast retransmit, etc.
+ */
+ }
+
+ /*
+ * If we're all caught up, we can cancel the
+ * retransmit timer. Otherwise, try to do
+ * some output on the interface. This will
+ * reset the retransmit timer if we did anything.
+ */
+
+ if (tmb_curlen(&(tcb->tcb_txbuf)) != 0) {
+ tcb->tcb_flags |= TCB_FLG_OUTPUT;
+ }
+ else {
+ TIMER_CLEAR(tcb->tcb_timer_retx);
+ }
+
+ break;
+
+ case TCPSTATE_FINWAIT_1:
+ ackamt = TCPSEQ_DIFF(ack,tcb->tcb_sendunack);
+ if (ackamt == 1) {
+ tcb->tcb_sendunack = ack;
+ if (flags & TCPFLG_FIN) {
+ _tcp_setstate(tcb,TCPSTATE_TIME_WAIT);
+ _tcp_canceltimers(tcb);
+ _tcp_preparectlmsg(tcb,TCPFLG_ACK);
+ TIMER_SET(tcb->tcb_timer_2msl,TCP_TIMEWAIT_TIMER);
+ }
+ else {
+ _tcp_setstate(tcb,TCPSTATE_FINWAIT_2);
+ }
+ }
+ break;
+
+ }
+}
+
+/* *********************************************************************
+ * _tcp_procdata(ti,tcb,seqnum,flags,buf)
+ *
+ * Process data in a received TCP packet - we'll put the
+ * data into the receive ring buffer, process the seqnum
+ * field, and prepare to send an ack.
+ *
+ * Input parameters:
+ * ti - tcp information
+ * tcb - tcb describing TCP session
+ * seqnum,flags - from the header of the received TCP packet
+ * buf - ebuf contianing data
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void _tcp_procdata(tcp_info_t *ti,tcb_t *tcb,uint32_t seqnum,
+ uint16_t flags,ebuf_t *buf)
+{
+ int datalen;
+ uint8_t *bp;
+ int rxwin,rwin;
+ uint32_t endseqnum;
+ uint32_t endrxwindow;
+ int reallen;
+
+ /*
+ * Figure out how much we're going to take. This should not
+ * exceed our buffer size because we advertised a window
+ * only big enough to fill our buffer.
+ */
+
+ bp = ebuf_ptr(buf); /* pointer to TCP data */
+ datalen = ebuf_remlen(buf); /* Size of TCP data */
+
+ /*
+ * If there's no data in the buffer, we can skip the data-related
+ * stuff and check for a possible FIN.
+ */
+
+ if (datalen != 0) {
+
+ /*
+ * Figure out if the data fits within the window. We don't deal
+ * with out-of-order segments, so the test is relatively
+ * simple: The received segment must contain (or match)
+ * the sequence number from "rcvnext" to the end of the receive
+ * window.
+ *
+ * Therefore: seqnum <= rcvnext < seqnum+datalen
+ */
+
+ rxwin = tmb_remlen(&(tcb->tcb_rxbuf)); /* receive window size */
+ endseqnum = (seqnum + datalen); /* seq # of end of segment */
+ endrxwindow = tcb->tcb_rcvack + rxwin; /* end of receive window */
+
+ /*
+ * The segment might include data outside the receive window
+ * (it's not supposed to, but it can). Crop the 'endseqnum'
+ * value at the rx window if necessary. Keep the earlier seqnum.
+ */
+//
+// XXX This is just plain broken - "endrxwindow" is the wrong thing to test.
+// if (TCPSEQ_LT(endrxwindow,endseqnum)) {
+// endseqnum = endrxwindow;
+// }
+
+ /*
+ * Test to see if the data is in sequence.
+ */
+
+ rwin = (TCPSEQ_LEQ(seqnum,tcb->tcb_rcvnext) &&
+ TCPSEQ_LT(tcb->tcb_rcvnext,endseqnum));
+
+ if (!rwin) {
+ DEBUGMSG(("Dropping out-of-order packet %u %u %u\n",seqnum,
+ tcb->tcb_rcvnext,endseqnum));
+ return;
+ }
+
+ /*
+ * The actual amount of new data is the distance from
+ * the "rcvnext" pointer to the end sequence number.
+ * typically this will be the entire packet, but we
+ * handle the case of receiving a partial duplicate segment.
+ * Do this by shortening the data length we're going to
+ * copy and adjusting the buffer pointer to point past the
+ * duplicate data. Normally this won't do anything.
+ */
+
+ reallen = endseqnum - tcb->tcb_rcvnext;
+ bp += (tcb->tcb_rcvnext - seqnum);
+
+ if (reallen != datalen) {
+ DEBUGMSG(("newdata(%d) does not match real length(%d)\n",reallen,datalen));
+ }
+
+ if (reallen > 0) {
+
+ /*
+ * Copy the data into the receive buffer. In the
+ * unlikely event that it doesn't fit, update the
+ * length so we'll only ack what we took.
+ */
+
+ reallen = tmb_copyin(&(tcb->tcb_rxbuf),bp,reallen,TRUE);
+
+ tcb->tcb_rcvnext += reallen;
+
+ /*
+ * Set the delayed-ack flag. If it's already set,
+ * then we've already received some data without acking
+ * it, so send the ack now, to encourage us to
+ * ack every other segment at least.
+ */
+
+ if (tcb->tcb_flags & TCB_FLG_DLYACK) {
+ _tcp_preparectlmsg(tcb,TCPFLG_ACK);
+ }
+ else {
+ tcb->tcb_flags |= TCB_FLG_DLYACK;
+ }
+ }
+ }
+
+ /*
+ * Handle the case of data in a FIN packet.
+ */
+
+ if (flags & TCPFLG_FIN) {
+
+ tcb->tcb_rcvnext++; /* Consume the FIN */
+
+ DEBUGMSG(("FIN rcvd in %d ack %u\n",tcb->tcb_state,tcb->tcb_rcvnext));
+
+ switch (tcb->tcb_state) {
+ case TCPSTATE_ESTABLISHED:
+
+ /*
+ * If a FIN is received in the ESTABLISHED state,
+ * go to CLOSE_WAIT.
+ */
+
+ tcb->tcb_flags &= ~TCB_FLG_DLYACK;
+ _tcp_setstate(tcb,TCPSTATE_CLOSE_WAIT);
+ _tcp_sendctlmsg(ti,tcb,TCPFLG_ACK,-1);
+ break;
+
+ case TCPSTATE_FINWAIT_1:
+
+ /*
+ * Two choices: Either we got a FIN or a FIN ACK.
+ * In either case, send an ack. The difference
+ * is what state we end up in.
+ */
+
+ if (flags & TCPFLG_ACK) {
+ /* Received: FIN ACK - go directly to TIME_WAIT */
+ _tcp_canceltimers(tcb);
+ _tcp_preparectlmsg(tcb,TCPFLG_ACK);
+ _tcp_setstate(tcb,TCPSTATE_TIME_WAIT);
+#if defined(CONFIG_MIPS_BRCM)
+ TIMER_SET(tcb->tcb_timer_2msl,TCP_SEND_TIMER);
+#else
+ TIMER_SET(tcb->tcb_timer_2msl,TCP_TIMEWAIT_TIMER);
+#endif
+ }
+ else {
+ /* Received: FIN - simultaneous close, go to CLOSING */
+ _tcp_setstate(tcb,TCPSTATE_CLOSING);
+ _tcp_preparectlmsg(tcb,TCPFLG_ACK);
+ }
+ break;
+
+ case TCPSTATE_FINWAIT_2:
+
+ /*
+ * Received a FIN in FINWAIT_2 - just transmit
+ * an ack and go to TIME_WAIT.
+ */
+
+ _tcp_canceltimers(tcb);
+ _tcp_preparectlmsg(tcb,TCPFLG_ACK);
+ _tcp_setstate(tcb,TCPSTATE_TIME_WAIT);
+ TIMER_SET(tcb->tcb_timer_2msl,TCP_TIMEWAIT_TIMER);
+ break;
+ }
+ }
+
+}
+
+/* *********************************************************************
+ * _tcp_rx_callback(ref,buf,destaddr,srcaddr)
+ *
+ * The IP layer calls this routine when a TCP packet is received.
+ * We dispatch the packet to appropriate handlers from here.
+ *
+ * Input parameters:
+ * ref - our tcp information (held by the ip stack for us)
+ * buf - the ebuf that we received
+ * destaddr,srcaddr - destination and source IP addresses
+ *
+ * Return value:
+ * ETH_DROP or ETH_KEEP, depending if we keep the packet or not
+ ********************************************************************* */
+
+static int _tcp_rx_callback(void *ref,ebuf_t *buf,uint8_t *destaddr,uint8_t *srcaddr)
+{
+ uint8_t pseudoheader[12];
+ int tcplen;
+ uint16_t calccksum;
+ uint16_t origcksum;
+ uint8_t *tcphdr;
+ uint16_t srcport;
+ uint16_t dstport;
+ uint32_t seqnum;
+ uint32_t acknum;
+ uint16_t window;
+ uint16_t flags;
+ tcb_t *tcb;
+ tcp_info_t *ti = (tcp_info_t *) ref;
+
+ /*
+ * get a pointer to the TCP header
+ */
+
+ tcplen = ebuf_length(buf);
+ tcphdr = ebuf_ptr(buf);
+
+ /*
+ * construct the pseudoheader for the cksum calculation
+ */
+
+ memcpy(&pseudoheader[0],srcaddr,IP_ADDR_LEN);
+ memcpy(&pseudoheader[4],destaddr,IP_ADDR_LEN);
+ pseudoheader[8] = 0;
+ pseudoheader[9] = IPPROTO_TCP;
+ pseudoheader[10] = (tcplen >> 8) & 0xFF;
+ pseudoheader[11] = (tcplen & 0xFF);
+
+ origcksum = ((uint16_t) tcphdr[16] << 8) | (uint16_t) tcphdr[17];
+ tcphdr[16] = tcphdr[17] = 0;
+
+ calccksum = ip_chksum(0,pseudoheader,sizeof(pseudoheader));
+ calccksum = ip_chksum(calccksum,tcphdr,tcplen);
+ calccksum = ~calccksum;
+
+ if (calccksum != origcksum) {
+ return ETH_DROP;
+ }
+
+ /* Read the other TCP header fields from the packet */
+
+ ebuf_get_u16_be(buf,srcport);
+ ebuf_get_u16_be(buf,dstport);
+ ebuf_get_u32_be(buf,seqnum);
+ ebuf_get_u32_be(buf,acknum);
+ ebuf_get_u16_be(buf,flags);
+ ebuf_get_u16_be(buf,window);
+ ebuf_skip(buf,4); /* skip checksum and urgent pointer */
+
+ /* Skip options in header */
+ if (TCPHDRSIZE(flags) < TCP_HDR_LENGTH) {
+ return ETH_DROP;
+ }
+ ebuf_skip(buf,(TCPHDRSIZE(flags) - TCP_HDR_LENGTH));
+
+ /*
+ * Okay, start looking for a matching TCB. If no matching TCB,
+ * send a RST.
+ * XXX Extra credit: rate-limit the RSTs.
+ */
+
+ tcb = _tcp_find_tcb(ti,srcport,dstport,srcaddr);
+ if (!tcb) {
+ DEBUGMSG(("Invalid TCB from %I, srcport=%u dstport=%u\n",srcaddr,srcport,dstport));
+ _tcp_sendreset(ti,srcaddr,seqnum+1,dstport,srcport);
+ return ETH_DROP; /* drop packet if no matching port */
+ }
+
+ /*
+ * Any activity on a TCB is enough to reset the keepalive timer
+ */
+
+ if (TCPSTATE_IN_SET(tcb->tcb_state,M_TCPSTATE_RESETKEEPALIVE)) {
+ TIMER_SET(tcb->tcb_timer_keep,TCP_KEEPALIVE_TIMER);
+ }
+
+ /*
+ * Some debugging
+ */
+
+#ifdef _TCP_DEBUG_
+ if (_tcp_dumpflags) _tcp_dumppktstate("Received",flags,
+ acknum,seqnum,ebuf_length(buf));
+#endif
+
+ /*
+ * If someone tries to reset us, just kill off the port.
+ * (except: if we were in SYN_RECEIVED, go back to LISTEN)
+ */
+
+ if (flags & TCPFLG_RST) {
+ if (tcb->tcb_state == TCPSTATE_SYN_RECEIVED) {
+ _tcp_setstate(tcb,TCPSTATE_LISTEN);
+ }
+ else {
+ _tcp_closetcb(ti,tcb);
+ }
+ return ETH_DROP;
+ }
+
+ /*
+ * Remember the window we got.
+ */
+
+ tcb->tcb_sendwindow = window;
+
+ /*
+ * What we do here depends on the current connection state
+ * Most of this is just from the connection state diagram we've
+ * all see way too often.
+ */
+
+ switch ( tcb->tcb_state ) {
+
+ case TCPSTATE_LISTEN:
+ if (flags & TCPFLG_SYN) {
+ tcb->tcb_rcvnext = seqnum + 1;
+ tcb->tcb_peerport = srcport;
+ memcpy(tcb->tcb_peeraddr,srcaddr,IP_ADDR_LEN);
+ TIMER_SET(tcb->tcb_timer_keep,TCP_KEEPALIVE_TIMER);
+ _tcp_setstate(tcb,TCPSTATE_SYN_RECEIVED);
+ _tcp_sendctlmsg(ti,tcb,TCPFLG_SYN | TCPFLG_ACK,TCP_RETX_TIMER);
+ }
+ return ETH_DROP; /* we ignore everything else */
+ break;
+
+ case TCPSTATE_SYN_SENT:
+
+ /*
+ * The only packets we pay attention to in SYN_SENT
+ * are packets with SYN flags.
+ */
+ if (flags & TCPFLG_SYN) {
+
+ /*
+ * Two choices: Either we got a SYN ACK (normal)
+ * or just a SYN (simultaneous open, rare)
+ */
+
+ if ((flags & TCPFLG_ACK) &&
+ (acknum == (tcb->tcb_sendunack + 1))) {
+ /*
+ * If we received a SYN ACK and the acknum
+ * matches our SYN's seqnum + 1, we want
+ * to transition from SYN_SENT to ESTABLISHED.
+ */
+ TIMER_SET(tcb->tcb_timer_keep,TCP_KEEPALIVE_TIMER);
+ _tcp_setstate(tcb,TCPSTATE_ESTABLISHED);
+ tcb->tcb_sendunack = acknum;
+ tcb->tcb_sendnext = tcb->tcb_sendunack;
+ tcb->tcb_rcvnext = seqnum + 1;
+ /*
+ * Send an ack, but don't bother with the timer.
+ * If the remote does not get our ack, it will
+ * retransmit the SYN ACK and we'll ack it from
+ * the "ESTABLISHED" state.
+ * Actually, is that really true?
+ */
+ _tcp_sendctlmsg(ti,tcb,TCPFLG_ACK,0);
+ }
+ else {
+ DEBUGMSG(("Simultaneous open: SYN received in SYN_SENT state\n"));
+ tcb->tcb_rcvnext++; /* consume the SYN */
+ _tcp_setstate(tcb,TCPSTATE_SYN_RECEIVED);
+ _tcp_sendctlmsg(ti,tcb,TCPFLG_SYN|TCPFLG_ACK,TCP_RETX_TIMER);
+ }
+ }
+
+ return ETH_DROP;
+ break;
+
+ case TCPSTATE_SYN_RECEIVED:
+ /*
+ * If we've received a SYN and someone sends us a SYN,
+ * and the sequence numbers don't match,
+ * send back a SYN ACK. (this doesn't sound right,
+ * does it? It's sort of what we do from LISTEN)
+ */
+
+ if (flags & TCPFLG_SYN) {
+ _tcp_sendctlmsg(ti,tcb,TCPFLG_SYN | TCPFLG_ACK,TCP_RETX_TIMER);
+ }
+
+ /*
+ * If we got an ack and the acknum is correct,
+ * switch the state to 'ESTABLISHED' and cancel
+ * the timer. We're ready to rock.
+ */
+
+ if ((flags & TCPFLG_ACK) &&
+ (acknum == (tcb->tcb_sendunack + 1))) {
+ _tcp_sendctlmsg(ti,tcb,TCPFLG_ACK,0);
+ tcb->tcb_sendunack = acknum;
+ tcb->tcb_sendnext = tcb->tcb_sendunack;
+ TIMER_SET(tcb->tcb_timer_keep,TCP_KEEPALIVE_TIMER);
+ _tcp_setstate(tcb,TCPSTATE_ESTABLISHED);
+ }
+
+ return ETH_DROP;
+ break;
+
+ case TCPSTATE_ESTABLISHED:
+ case TCPSTATE_FINWAIT_1:
+ case TCPSTATE_FINWAIT_2:
+
+ /*
+ * ESTABLISHED, FINWAIT_1, and FINWAIT_2 can all
+ * carry data. Process the data here. If the
+ * segment also contains a FIN, these routines
+ * will handle that.
+ */
+
+ if (flags & TCPFLG_ACK) {
+ _tcp_procack(ti,tcb,acknum,flags);
+ }
+ _tcp_procdata(ti,tcb,seqnum,flags,buf);
+ break;
+
+ case TCPSTATE_CLOSING:
+ if (acknum == (tcb->tcb_sendunack + 1)) {
+ _tcp_setstate(tcb,TCPSTATE_TIME_WAIT);
+ _tcp_canceltimers(tcb);
+ TIMER_SET(tcb->tcb_timer_2msl,TCP_TIMEWAIT_TIMER);
+ }
+ break;
+
+ case TCPSTATE_LAST_ACK:
+ if (acknum == (tcb->tcb_sendunack + 1)) {
+ /* Ack matches, just close the TCB here. */
+ _tcp_closetcb(ti,tcb);
+ /* and free it. */
+ _tcp_freetcb(ti,tcb);
+ }
+ else {
+ _tcp_sendctlmsg(ti,tcb,TCPFLG_ACK | TCPFLG_FIN,TCP_RETX_TIMER);
+ }
+ break;
+
+ case TCPSTATE_TIME_WAIT:
+ if (!(flags & TCPFLG_RST)) {
+ tcb->tcb_txflags = TCPFLG_ACK;
+ TIMER_SET(tcb->tcb_timer_2msl,TCP_TIMEWAIT_TIMER);
+ _tcp_protosend(ti,tcb);
+ }
+ break;
+ }
+
+ /*
+ * If we're expected to transmit something, do it now.
+ */
+
+ if (tcb->tcb_flags & TCB_FLG_OUTPUT) {
+ _tcp_output(ti,tcb);
+ tcb->tcb_flags &= ~(TCB_FLG_OUTPUT | TCB_FLG_SENDMSG);
+ }
+
+ if (tcb->tcb_flags & TCB_FLG_SENDMSG) {
+ _tcp_protosend(ti,tcb);
+ }
+
+ /* We always make a copy of the data, so drop the packet. */
+ return ETH_DROP;
+}
+
+/* *********************************************************************
+ * _tcp_fasttimo(ti)
+ *
+ * Handle "fast timeout" for active TCP sockets.
+ *
+ * Input parameters:
+ * ti - tcp_info structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+static void _tcp_fasttimo(tcp_info_t *ti)
+{
+ tcb_t *tcb;
+ queue_t *qb;
+
+ /*
+ * First, reset the timer so we'll end up here
+ * again in another 200ms
+ */
+
+ TIMER_SET(ti->ti_fasttimer,TCP_FAST_TIMER); /* 200ms */
+
+ /*
+ * Now, walk down the list of TCBs and handle
+ * all the timers.
+ */
+
+ for (qb = ti->ti_tcblist.q_next; qb != &(ti->ti_tcblist); qb = qb->q_next) {
+ tcb = (tcb_t *) qb;
+ if (tcb->tcb_flags & TCB_FLG_DLYACK) {
+ tcb->tcb_flags &= ~TCB_FLG_DLYACK;
+ _tcp_sendctlmsg(ti,tcb,TCPFLG_ACK,-1);
+ }
+ }
+
+ /*
+ * While we're here, increment TCP's initial sequence number.
+ * BSD suggests 128000 every second, so we'll add 25600 every 200ms.
+ */
+
+ ti->ti_iss += 25600;
+
+}
+
+
+/* *********************************************************************
+ * _tcp_poll(arg)
+ *
+ * CFE calls this routine periodically to allow us to check
+ * and update timers, etc.
+ *
+ * Input parameters:
+ * arg - our tcp information (held by the timer module for us)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void _tcp_poll(void *arg)
+{
+ tcb_t *tcb;
+ queue_t *qb;
+ tcp_info_t *ti = (tcp_info_t *) arg;
+
+ /*
+ * Handle the "fast" timer. We do this every 200ms
+ */
+
+ if (TIMER_EXPIRED(ti->ti_fasttimer)) {
+ _tcp_fasttimo(ti);
+ /* timer will be reset by the _tcp_fasttimo routine */
+ }
+
+ /*
+ * Check the TCBs for the "slow" timers.
+ */
+
+ for (qb = ti->ti_tcblist.q_next; qb != &(ti->ti_tcblist); qb = qb->q_next) {
+ tcb = (tcb_t *) qb;
+
+ /*
+ * Check the retransmit timer. This is used during connection
+ * attempts to retransmit control messages, or also during
+ * regular data transfer to retransmit messages that are not
+ * acknowledged.
+ *
+ * XXX use the computed round-trip timer here
+ */
+
+ if (TIMER_EXPIRED(tcb->tcb_timer_retx)) {
+ TIMER_CLEAR(tcb->tcb_timer_retx); /* unless it is reset */
+
+ DEBUGMSG(("Retransmit timer expired, retrycnt=%d\n",tcb->tcb_retrycnt));
+
+ switch (tcb->tcb_state) {
+ case TCPSTATE_ESTABLISHED:
+ /*
+ * wind the send seqnum back to the last unacknowledged data,
+ * and send it out again.
+ */
+ TIMER_SET(tcb->tcb_timer_retx,TCP_RETX_TIMER);
+ tcb->tcb_retrycnt++;
+ tcb->tcb_sendnext = tcb->tcb_sendunack;
+ _tcp_output(ti,tcb);
+ break;
+
+ case TCPSTATE_SYN_SENT:
+ TIMER_SET(tcb->tcb_timer_retx,(TCP_RETX_TIMER << tcb->tcb_retrycnt));
+ tcb->tcb_retrycnt++;
+ tcb->tcb_sendnext = tcb->tcb_sendunack;
+ _tcp_protosend(ti,tcb);
+ break;
+
+ }
+ }
+
+ /*
+ * Check the keepalive timer. This is used during connection
+ * attempts to time out the connection, and _can_ be used for
+ * keepalives during established sessions.
+ *
+ * Our TCP does not bother with keepalive messages.
+ */
+
+ if (TIMER_EXPIRED(tcb->tcb_timer_keep)) {
+ TIMER_CLEAR(tcb->tcb_timer_keep); /* unless it is reset */
+ DEBUGMSG(("Keepalive timer expired in state %d\n",tcb->tcb_state));
+ if (TCPSTATE_IN_SET(tcb->tcb_state,M_TCPSTATE_CONNINPROGRESS)) {
+ DEBUGMSG(("Canceling pending connection\n"));
+ _tcp_aborttcb(ti,tcb);
+ }
+ }
+
+ /*
+ * Check the 2MSL timer. This is used in the TIME_WAIT state
+ * to return the tcb to the free list after the time wait
+ * period elapses.
+ */
+
+ if (TIMER_EXPIRED(tcb->tcb_timer_2msl)) {
+ TIMER_CLEAR(tcb->tcb_timer_2msl); /* will not be reset */
+ DEBUGMSG(("2MSL timer expired in state %d\n",tcb->tcb_state));
+ if (tcb->tcb_state == TCPSTATE_TIME_WAIT) {
+ DEBUGMSG(("Freeing TCB\n"));
+ _tcp_closetcb(ti,tcb);
+ _tcp_freetcb(ti,tcb);
+ }
+ }
+
+ }
+
+}
+
+
diff --git a/cfe/cfe/net/net_tcp.h b/cfe/cfe/net/net_tcp.h
new file mode 100755
index 0000000..fa772e6
--- /dev/null
+++ b/cfe/cfe/net/net_tcp.h
@@ -0,0 +1,83 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * TCP Protocol Definitions File: net_tcp.h
+ *
+ * This file contains TCP protocol-specific definitions
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+/* *********************************************************************
+ * TCP Flags - keep in sync with net_api.h
+ ********************************************************************* */
+
+#define TCPFLG_NODELAY 1 /* disable nagle */
+#define TCPFLG_NBIO 2 /* Non-blocking I/O */
+
+#define TCPSTATUS_NOTCONN 0
+#define TCPSTATUS_CONNECTING 1
+#define TCPSTATUS_CONNECTED 2
+
+/* *********************************************************************
+ * TCP API
+ ********************************************************************* */
+
+typedef struct tcp_info_s tcp_info_t;
+
+tcp_info_t *_tcp_init(ip_info_t *ipi,void *ref);
+void _tcp_uninit(tcp_info_t *info);
+
+int _tcp_socket(tcp_info_t *info);
+int _tcp_connect(tcp_info_t *ti,int s,uint8_t *dest,uint16_t port);
+int _tcp_close(tcp_info_t *ti,int s);
+int _tcp_send(tcp_info_t *ti,int s,uint8_t *buf,int len);
+int _tcp_recv(tcp_info_t *ti,int s,uint8_t *buf,int len);
+int _tcp_bind(tcp_info_t *ti,int s,uint16_t port);
+int _tcp_peeraddr(tcp_info_t *ti,int s,uint8_t *addr,uint16_t *port);
+int _tcp_listen(tcp_info_t *ti,int s,uint16_t port);
+int _tcp_status(tcp_info_t *ti,int s,unsigned int *connflag,int *rxready,int *rxeof);
+int _tcp_debug(tcp_info_t *ti,int s,int arg);
+int _tcp_setflags(tcp_info_t *ti,int s,unsigned int flags);
+int _tcp_getflags(tcp_info_t *ti,int s,unsigned int *flags);
+
+void _tcp_poll(void *arg);
+
+
diff --git a/cfe/cfe/net/net_tcp_internal.h b/cfe/cfe/net/net_tcp_internal.h
new file mode 100755
index 0000000..1e3fc6d
--- /dev/null
+++ b/cfe/cfe/net/net_tcp_internal.h
@@ -0,0 +1,244 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * TCP Protocol Internal Definitions File: net_tcp_internal.h
+ *
+ * This file contains the structures and constants needed to
+ * maintain TCP connections.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+/* *********************************************************************
+ * TCP Constants
+ ********************************************************************* */
+
+
+#define TCP_MAX_PORTS 8
+#define TCP_MAX_TCBS 16
+#if defined(CONFIG_MIPS_BRCM)
+#define TCP_BUF_SIZE (20 * 1024)
+#else
+#define TCP_BUF_SIZE 65536
+#endif
+
+#define TCP_MAX_SEG_SIZE 1400
+
+#define TCP_CONNECT_TIMER (30*CFE_HZ)
+#define TCP_RETX_TIMER (1*CFE_HZ)
+#define TCP_TIMEWAIT_TIMER (30*CFE_HZ)
+#define TCP_SEND_TIMER (CFE_HZ)
+
+#define TCP_FAST_TIMER (CFE_HZ/5) /* 200ms */
+#define TCP_KEEPALIVE_TIMER (CFE_HZ*60) /* one minute */
+
+
+/* *********************************************************************
+ * TCP Protocol
+ ********************************************************************* */
+
+#define TCPFLG_FIN 0x0001
+#define TCPFLG_SYN 0x0002
+#define TCPFLG_RST 0x0004
+#define TCPFLG_PSH 0x0008
+#define TCPFLG_ACK 0x0010
+#define TCPFLG_URG 0x0020
+#define TCPHDRSIZE(flg) (((flg) >> 12)*4)
+#define TCPHDRFLG(size) (((size)/4)<<12)
+
+#define TCP_HDR_LENGTH 20
+
+#define TCP_MAX_SEG_OPT 0x0204
+
+/* *********************************************************************
+ * TCP State machine
+ ********************************************************************* */
+
+/*
+ * TCB states, see RFC
+ */
+
+#define TCPSTATE_CLOSED 0
+#define TCPSTATE_LISTEN 1
+#define TCPSTATE_SYN_SENT 2
+#define TCPSTATE_SYN_RECEIVED 3
+#define TCPSTATE_ESTABLISHED 4
+#define TCPSTATE_CLOSE_WAIT 5
+#define TCPSTATE_FINWAIT_1 6
+#define TCPSTATE_FINWAIT_2 7
+#define TCPSTATE_CLOSING 8
+#define TCPSTATE_LAST_ACK 9
+#define TCPSTATE_TIME_WAIT 10
+
+/*
+ * Masks for TCP states - we use these so we can make
+ * bit vectors of states for easy tests.
+ */
+
+#define M_TCPSTATE_CLOSED (1 << TCPSTATE_CLOSED)
+#define M_TCPSTATE_LISTEN (1 << TCPSTATE_LISTEN)
+#define M_TCPSTATE_SYN_SENT (1 << TCPSTATE_SYN_SENT)
+#define M_TCPSTATE_SYN_RECEIVED (1 << TCPSTATE_SYN_RECEIVED)
+#define M_TCPSTATE_ESTABLISHED (1 << TCPSTATE_ESTABLISHED)
+#define M_TCPSTATE_CLOSE_WAIT (1 << TCPSTATE_CLOSE_WAIT)
+#define M_TCPSTATE_FINWAIT_1 (1 << TCPSTATE_FINWAIT_1)
+#define M_TCPSTATE_FINWAIT_2 (1 << TCPSTATE_FINWAIT_2)
+#define M_TCPSTATE_CLOSING (1 << TCPSTATE_CLOSING)
+#define M_TCPSTATE_LAST_ACK (1 << TCPSTATE_LAST_ACK)
+#define M_TCPSTATE_TIME_WAIT (1 << TCPSTATE_TIME_WAIT)
+#define M_TCPSTATE_CLOSED (1 << TCPSTATE_CLOSED)
+
+/*
+ * This macro returns true if a given state is in a
+ * set of states (defined below)
+ */
+
+#define TCPSTATE_IN_SET(state,set) ((1 << (state)) & (set))
+
+/*
+ * Intresting groups of TCP states
+ */
+
+/* ABORTSTATES - tcp_abort will send a RST if our TCB is one of these. */
+#define M_TCPSTATE_ABORTSTATES \
+ M_TCPSTATE_SYN_SENT | M_TCPSTATE_SYN_RECEIVED | M_TCPSTATE_ESTABLISHED | \
+ M_TCPSTATE_FINWAIT_1 | M_TCPSTATE_FINWAIT_2 | M_TCPSTATE_CLOSING | \
+ M_TCPSTATE_LAST_ACK | M_TCPSTATE_CLOSE_WAIT
+
+/* SEND_OK - tcp_send will send data if our TCB is one of these */
+#define M_TCPSTATE_SEND_OK \
+ M_TCPSTATE_ESTABLISHED | M_TCPSTATE_CLOSE_WAIT
+
+/* RECV_OK - tcp_recv will pass up data if our TCB is in one of these */
+#define M_TCPSTATE_RECV_OK \
+ M_TCPSTATE_ESTABLISHED | M_TCPSTATE_CLOSE_WAIT
+
+/* PEERADDR_OK - tcp_peeraddr will return a value if TCB is in one of these */
+#define M_TCPSTATE_PEERADDR_OK \
+ M_TCPSTATE_SYN_SENT | M_TCPSTATE_SYN_RECEIVED | M_TCPSTATE_ESTABLISHED | \
+ M_TCPSTATE_FINWAIT_1 | M_TCPSTATE_FINWAIT_2 | M_TCPSTATE_CLOSING | \
+ M_TCPSTATE_LAST_ACK | M_TCPSTATE_CLOSE_WAIT
+
+/* RESETKEEPALIVE - reset keepalive timer in these states */
+#define M_TCPSTATE_RESETKEEPALIVE \
+ M_TCPSTATE_ESTABLISHED | M_TCPSTATE_CLOSE_WAIT | M_TCPSTATE_FINWAIT_1 | \
+ M_TCPSTATE_FINWAIT_2 | M_TCPSTATE_CLOSING | M_TCPSTATE_LAST_ACK
+
+#define CONNINPROGRESS - connection is in progress in these states */
+#define M_TCPSTATE_CONNINPROGRESS \
+ M_TCPSTATE_LISTEN | M_TCPSTATE_SYN_SENT | M_TCPSTATE_SYN_RECEIVED
+
+
+/*
+ * TCP flags for the control block
+ */
+
+#define TCB_FLG_OUTPUT 1 /* need to call tcp_output */
+#define TCB_FLG_SENDMSG 2
+#define TCB_FLG_DLYACK 4 /* delayed ack is pending */
+
+/* *********************************************************************
+ * TCP Control Block
+ ********************************************************************* */
+
+typedef struct tcb_s {
+ queue_t tcb_qb; /* next/previous in list */
+ int tcb_socknum; /* socket number, index into table */
+
+ int tcb_state; /* current connection state */
+
+ uint8_t tcb_peeraddr[IP_ADDR_LEN]; /* Peer's IP Address */
+ uint16_t tcb_peerport; /* Peer's port address */
+ uint16_t tcb_lclport; /* My port address */
+
+ uint16_t tcb_txflags; /* packet flags for next tx packet */
+
+ cfe_timer_t tcb_timer_2msl; /* 2MSL timer, used in TIME_WAIT */
+ cfe_timer_t tcb_timer_keep; /* Timer for keepalives and connections */
+ cfe_timer_t tcb_timer_retx; /* send retransmission timer */
+ cfe_timer_t tcb_timer_pers; /* Persist timer */
+
+ int tcb_retrycnt; /* Retry counter */
+
+ int tcb_mtu; /* MTU if underlying link */
+ unsigned int tcb_flags; /* Misc protocol flags */
+ unsigned int tcb_sockflags; /* flags set by user api */
+
+ /*
+ * Buffers
+ */
+
+ tcpmodbuf_t tcb_txbuf; /* Transmit buffer */
+ tcpmodbuf_t tcb_rxbuf; /* Receive buffer */
+
+ /*
+ * Send sequence variables
+ */
+
+ uint32_t tcb_sendunack; /* oldest unacknowledged seqnum */
+ uint32_t tcb_sendnext; /* Next seqnum to send */
+ uint32_t tcb_sendwindow; /* Last advertised send window */
+
+ /*
+ * Receive sequence variables
+ */
+
+ uint32_t tcb_rcvnext; /* next in-order receive seq num */
+ uint32_t tcb_rcvack; /* last transmitted acknowledgement */
+
+ /*
+ * Window management variables
+ */
+ int tcb_dup_ackcnt; /* Duplicate ack counter */
+
+} tcb_t;
+
+/* *********************************************************************
+ * Macros to muck with sequence numbers
+ ********************************************************************* */
+
+#define TCPSEQ_LT(a,b) ((int)((a)-(b)) < 0)
+#define TCPSEQ_LEQ(a,b) ((int)((a)-(b)) <= 0)
+#define TCPSEQ_GT(a,b) ((int)((a)-(b)) > 0)
+#define TCPSEQ_GEQ(a,b) ((int)((a)-(b)) >= 0)
+
+#define TCPSEQ_DIFF(a,b) ((int)((a)-(b)))
+
diff --git a/cfe/cfe/net/net_tcpbuf.c b/cfe/cfe/net/net_tcpbuf.c
new file mode 100644
index 0000000..08e690b
--- /dev/null
+++ b/cfe/cfe/net/net_tcpbuf.c
@@ -0,0 +1,298 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * TCP Protocol File: net_tcp.c
+ *
+ * This file contains a very simple TCP.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_error.h"
+
+#include "net_tcpbuf.h"
+
+
+
+/* *********************************************************************
+ * tmb_init(buf)
+ *
+ * Initialize a modulo buffer's pointers to the "empty" state
+ *
+ * Input parameters:
+ * buf - modulo buffer structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void tmb_init(tcpmodbuf_t *buf)
+{
+ buf->tmb_addptr = 0;
+ buf->tmb_remptr = 0;
+ buf->tmb_len = 0;
+}
+
+/* *********************************************************************
+ * tmb_adjust(buf,amt)
+ *
+ * Move the "remove" pointer ahead by 'amt' without retrieving the
+ * data.
+ *
+ * Input parameters:
+ * buf - modulo buffer structure
+ * amt - number of bytes to move
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+void tmb_adjust(tcpmodbuf_t *buf,int amt)
+{
+ /* XXX should we check for moving to far? */
+ buf->tmb_len -= amt;
+ buf->tmb_remptr = (buf->tmb_remptr + amt) % buf->tmb_bufsize;
+}
+
+/* *********************************************************************
+ * tmb_alloc(buf,size)
+ *
+ * Allocate memory for the modulo buffer.
+ *
+ * Input parameters:
+ * buf - modulo buffer structure
+ * size - size of data in modulo buffer
+ *
+ * Return value:
+ * 0 if ok
+ * -1 if error
+ ********************************************************************* */
+
+int tmb_alloc(tcpmodbuf_t *buf,int size)
+{
+ buf->tmb_buf = KMALLOC(size,0);
+ if (!buf->tmb_buf) return -1;
+ buf->tmb_bufsize = size;
+
+ tmb_init(buf);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * tmb_free(buf)
+ *
+ * Free memory associated with the modulo buffer
+ *
+ * Input parameters:
+ * buf - modulo buffer
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void tmb_free(tcpmodbuf_t *buf)
+{
+ if (buf->tmb_buf) KFREE(buf->tmb_buf);
+ buf->tmb_buf = NULL;
+}
+
+
+/* *********************************************************************
+ * tmb_copyin(tmb,buf,len,update)
+ *
+ * Copy data into the modulo buffer at the 'add' pointer
+ *
+ * Input parameters:
+ * tmb - modulo buffer structure
+ * buf,len - buffer and length of buffer to copy in
+ * update - true to advance 'add' pointer (usually true for copyin)
+ *
+ * Return value:
+ * number of bytes actually added to the buffer
+ ********************************************************************* */
+
+int tmb_copyin(tcpmodbuf_t *tmb,uint8_t *buf,int len,int update)
+{
+ int maxlen;
+ int l;
+ int newptr;
+ int retlen;
+
+ if (len == 0) return 0;
+
+ /* Set 'maxlen' to the max # of bytes we will send now */
+ maxlen = tmb->tmb_bufsize - tmb->tmb_len;
+ if (maxlen > len) maxlen = len;
+
+ retlen = maxlen; /* we'll return this later. */
+
+ /* Copy the bytes into the buffer and deal with buffer wrap */
+ l = tmb->tmb_bufsize - tmb->tmb_addptr;
+ if (l > maxlen) l = maxlen;
+
+ memcpy(tmb->tmb_buf + tmb->tmb_addptr,buf,l);
+ maxlen -= l;
+ buf += l;
+
+ if (maxlen) {
+ memcpy(tmb->tmb_buf,buf,maxlen);
+ newptr = maxlen;
+ }
+ else {
+ newptr = tmb->tmb_addptr + l;
+ }
+
+ if (update) {
+ tmb->tmb_len += retlen; /* this many more in the buffer */
+ tmb->tmb_addptr = newptr;
+ }
+
+ return retlen;
+}
+
+/* *********************************************************************
+ * tmb_copyout(tmb,buf,len,update)
+ *
+ * Copy data out of the modulo buffer from the 'remove' pointer
+ *
+ * Input parameters:
+ * tmb - modulo buffer structure
+ * buf,len - buffer and length of buffer to copy out
+ * update - true to advance 'remove' pointer
+ *
+ * Return value:
+ * number of bytes actually removed from the buffer
+ ********************************************************************* */
+
+int tmb_copyout(tcpmodbuf_t *tmb,uint8_t *buf,int len,int update)
+{
+ int maxlen;
+ int l;
+ int newptr;
+ int retlen;
+
+ /* Compute how many bytes to return */
+ maxlen = tmb->tmb_len;
+ if (maxlen > len) maxlen = len;
+
+ retlen = maxlen;
+
+ l = tmb->tmb_bufsize - tmb->tmb_remptr;
+ if (l > maxlen) l = maxlen;
+
+ memcpy(buf,tmb->tmb_buf + tmb->tmb_remptr,l);
+ buf += l;
+ maxlen -= l;
+
+ if (maxlen) {
+ memcpy(buf,tmb->tmb_buf,maxlen);
+ newptr = maxlen;
+ }
+ else {
+ newptr = tmb->tmb_remptr + l;
+ }
+
+ if (update) {
+ tmb->tmb_len -= retlen;
+ tmb->tmb_remptr = newptr;
+ }
+
+ return retlen;
+}
+
+/* *********************************************************************
+ * tmb_copyout2(tmb,buf,offset,len)
+ *
+ * Copy data out of the modulo buffer from a specific offset from
+ * the remove pointer. This is done without updating the
+ * remove pointer - we use this to dig data out when segmenting
+ * packets for transmission.
+ *
+ * Input parameters:
+ * tmb - modulo buffer structure
+ * buf,len - buffer and length of buffer to copy out
+ * offset - offset from remove pointer to start
+ *
+ * Return value:
+ * number of bytes actually copied out of the buffer
+ ********************************************************************* */
+
+int tmb_copyout2(tcpmodbuf_t *tmb,uint8_t *buf,int offset,int len)
+{
+ int maxlen;
+ int l;
+ int retlen;
+ int remptr;
+
+ /* Compute how many bytes to return */
+ maxlen = tmb->tmb_len - offset;
+
+ /* if offset is beyond length, get out now. */
+ if (maxlen <= 0) return 0;
+
+ /* otherwise choose min(max_can_copy,max_to_copy) */
+ if (maxlen > len) maxlen = len;
+ retlen = maxlen;
+
+ /* Adjust remove pointer for offset */
+ remptr = (tmb->tmb_remptr + offset) % tmb->tmb_bufsize;
+
+ l = tmb->tmb_bufsize - remptr;
+ if (l > maxlen) l = maxlen;
+
+ memcpy(buf,tmb->tmb_buf + remptr,l);
+ buf += l;
+ maxlen -= l;
+
+ if (maxlen) {
+ memcpy(buf,tmb->tmb_buf,maxlen);
+ }
+
+ return retlen;
+}
+
diff --git a/cfe/cfe/net/net_tcpbuf.h b/cfe/cfe/net/net_tcpbuf.h
new file mode 100644
index 0000000..0c251e3
--- /dev/null
+++ b/cfe/cfe/net/net_tcpbuf.h
@@ -0,0 +1,83 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * TCP Protocol Definitions File: net_tcp.h
+ *
+ * This file contains TCP protocol-specific definitions
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define tmb_remlen(tmb) ((tmb)->tmb_bufsize - (tmb)->tmb_len)
+#define tmb_curlen(tmb) ((tmb)->tmb_len)
+
+
+/* *********************************************************************
+ * Modulo Buffer
+ ********************************************************************* */
+
+typedef struct tcpmodbuf_s {
+ uint8_t *tmb_buf; /* Buffer */
+ int tmb_bufsize; /* size of buffer */
+ int tmb_addptr; /* current "add" pointer */
+ int tmb_remptr; /* current "remove" pointer */
+ int tmb_len; /* amount of data in the buffer */
+} tcpmodbuf_t;
+
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+void tmb_init(tcpmodbuf_t *buf);
+void tmb_adjust(tcpmodbuf_t *buf,int amt);
+int tmb_alloc(tcpmodbuf_t *buf,int size);
+void tmb_free(tcpmodbuf_t *buf);
+int tmb_copyin(tcpmodbuf_t *tmb,uint8_t *buf,int len,int update);
+int tmb_copyout(tcpmodbuf_t *tmb,uint8_t *buf,int len,int update);
+int tmb_copyout2(tcpmodbuf_t *tmb,uint8_t *buf,int offset,int len);
+
+
+
+
+
diff --git a/cfe/cfe/net/net_tftp.c b/cfe/cfe/net/net_tftp.c
new file mode 100644
index 0000000..1c3e799
--- /dev/null
+++ b/cfe/cfe/net/net_tftp.c
@@ -0,0 +1,921 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * TFTP Client File: net_tftp.c
+ *
+ * This module contains a TFTP client.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_error.h"
+#include "cfe_fileops.h"
+
+/* Foxconn add start by Cliff Wang, 03/23/2010 */
+#include "cfe_console.h"
+/* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+
+#include "cfe.h"
+
+#include "cfe_loader.h"
+
+#include "net_api.h"
+
+
+
+/* *********************************************************************
+ * TFTP protocol
+ ********************************************************************* */
+
+#define UDP_PROTO_TFTP 69
+
+#define TFTP_BLOCKSIZE 512
+
+#define TFTP_OP_RRQ 1
+#define TFTP_OP_WRQ 2
+#define TFTP_OP_DATA 3
+#define TFTP_OP_ACK 4
+#define TFTP_OP_ERROR 5
+
+#define TFTP_ERR_DISKFULL 3
+
+#define TFTP_MAX_RETRIES 8
+
+#define TFTP_RRQ_TIMEOUT 1 /* seconds */
+#define TFTP_RECV_TIMEOUT 1 /* seconds */
+
+/* *********************************************************************
+ * TFTP context
+ ********************************************************************* */
+
+typedef struct tftp_fsctx_s {
+ int dummy;
+} tftp_fsctx_t;
+
+typedef struct tftp_info_s {
+ int tftp_socket;
+ uint8_t tftp_data[TFTP_BLOCKSIZE];
+ int tftp_blklen;
+ int tftp_blkoffset;
+ int tftp_fileoffset;
+ uint16_t tftp_blknum;
+ uint8_t tftp_ipaddr[IP_ADDR_LEN];
+ int tftp_lastblock;
+ int tftp_error;
+ int tftp_filemode;
+ char *tftp_filename;
+} tftp_info_t;
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+static int tftp_fileop_init(void **fsctx,void *devicename);
+static int tftp_fileop_open(void **ref,void *fsctx,char *filename,int mode);
+static int tftp_fileop_read(void *ref,uint8_t *buf,int len);
+static int tftp_fileop_write(void *ref,uint8_t *buf,int len);
+static int tftp_fileop_seek(void *ref,int offset,int how);
+static void tftp_fileop_close(void *ref);
+static void tftp_fileop_uninit(void *fsctx);
+
+/* Foxconn add start by Cliff Wang, 03/23/2010 */
+int tftp_max_retries = TFTP_MAX_RETRIES;
+int tftp_rrq_timeout = TFTP_RRQ_TIMEOUT;
+int tftp_recv_timeout = TFTP_RECV_TIMEOUT;
+/* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+/* *********************************************************************
+ * TFTP fileio dispatch table
+ ********************************************************************* */
+
+const fileio_dispatch_t tftp_fileops = {
+ "tftp",
+ LOADFLG_NOBB | FSYS_TYPE_NETWORK,
+ tftp_fileop_init,
+ tftp_fileop_open,
+ tftp_fileop_read,
+ tftp_fileop_write,
+ tftp_fileop_seek,
+ tftp_fileop_close,
+ tftp_fileop_uninit
+};
+
+
+/* *********************************************************************
+ * _tftp_open(info,hostname,filename,mode)
+ *
+ * Open a file on a remote host, using the TFTP protocol.
+ *
+ * Input parameters:
+ * info - TFTP information
+ * hostname - host name or IP address of remote host
+ * filename - name of file on remote system
+ * mode - file open mode, read or write
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int _tftp_open(tftp_info_t *info,char *hostname,char *filename,int mode)
+{
+ ebuf_t *buf = NULL;
+ const char *datamode = "octet";
+ uint16_t type,error,block;
+ int res;
+ int retries;
+
+ /*
+ * Look up the remote host's IP address
+ */
+
+ res = dns_lookup(hostname,info->tftp_ipaddr);
+ if (res < 0) return res;
+
+ /*
+ * Open a UDP socket to the TFTP server
+ */
+
+ info->tftp_socket = udp_socket(UDP_PROTO_TFTP);
+ info->tftp_lastblock = 0;
+ info->tftp_error = 0;
+ info->tftp_filemode = mode;
+
+ /*
+ * Try to send the RRQ packet to open the file
+ */
+
+ for (retries = 0; retries < TFTP_MAX_RETRIES; retries++) {
+
+ buf = udp_alloc();
+ if (!buf) break;
+
+ if (info->tftp_filemode == FILE_MODE_READ) {
+ ebuf_append_u16_be(buf,TFTP_OP_RRQ); /* read file */
+ }
+ else {
+ ebuf_append_u16_be(buf,TFTP_OP_WRQ); /* write file */
+ }
+ ebuf_append_bytes(buf,filename,strlen(filename)+1);
+ ebuf_append_bytes(buf,datamode,strlen(datamode)+1);
+
+ udp_send(info->tftp_socket,buf,info->tftp_ipaddr);
+
+ buf = udp_recv_with_timeout(info->tftp_socket,TFTP_RRQ_TIMEOUT);
+ if (buf) break;
+ }
+
+ /*
+ * If we got no response, bail now.
+ */
+
+ if (!buf) {
+ udp_close(info->tftp_socket);
+ info->tftp_socket = -1;
+ return CFE_ERR_TIMEOUT;
+ }
+
+ /*
+ * Otherwise, process the response.
+ */
+
+ ebuf_get_u16_be(buf,type);
+
+ switch (type) {
+ case TFTP_OP_ACK:
+ /*
+ * Acks are what we get back on a WRQ command,
+ * but are otherwise unexpected.
+ */
+ if (info->tftp_filemode == FILE_MODE_WRITE) {
+ udp_connect(info->tftp_socket,(uint16_t) buf->eb_usrdata);
+ info->tftp_blknum = 1;
+ info->tftp_blklen = 0;
+ udp_free(buf);
+ return 0;
+ break;
+ }
+ /* fall through */
+ case TFTP_OP_RRQ:
+ case TFTP_OP_WRQ:
+ default:
+ /*
+ * we aren't expecting any of these messages
+ */
+ udp_free(buf);
+ udp_close(info->tftp_socket);
+ info->tftp_socket = -1;
+ return CFE_ERR_PROTOCOLERR;
+
+ case TFTP_OP_ERROR:
+ /*
+ * Process the error return (XXX: remove xprintf here)
+ */
+ ebuf_get_u16_be(buf,error);
+ xprintf("TFTP error %d: %s\n",error,ebuf_ptr(buf));
+ udp_free(buf);
+ udp_close(info->tftp_socket);
+ info->tftp_socket = -1;
+ return CFE_ERR_PROTOCOLERR;
+
+ case TFTP_OP_DATA:
+ /*
+ * Yay, we've got data! Store the first block.
+ */
+ ebuf_get_u16_be(buf,block);
+ udp_connect(info->tftp_socket,(uint16_t) buf->eb_usrdata);
+ info->tftp_blknum = block;
+ info->tftp_blklen = ebuf_length(buf);
+ ebuf_get_bytes(buf,info->tftp_data,ebuf_length(buf));
+ udp_free(buf);
+ if (info->tftp_blklen < TFTP_BLOCKSIZE) {
+ info->tftp_lastblock = 1; /* EOF */
+ }
+ return 0;
+ break;
+
+ }
+}
+
+
+/* *********************************************************************
+ * _tftp_readmore(info)
+ *
+ * Read the next block of the file. We do this by acking the
+ * previous block. Once that block is acked, the TFTP server
+ * should send the next block to us.
+ *
+ * Input parameters:
+ * info - TFTP information
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int _tftp_readmore(tftp_info_t *info)
+{
+ ebuf_t *buf;
+ uint16_t cmd,block;
+ int retries;
+
+ /*
+ * If we've already read the last block, there is no more
+ */
+
+ if (info->tftp_lastblock) return 1;
+ if (info->tftp_error) return CFE_ERR_TIMEOUT;
+
+ /*
+ * Otherwise, ack the current block so another one will come
+ */
+
+ for (retries = 0; retries < TFTP_MAX_RETRIES; retries++) {
+
+ buf = udp_alloc();
+ if (!buf) return -1;
+
+ /*
+ * Send the ack
+ */
+
+ ebuf_append_u16_be(buf,TFTP_OP_ACK);
+ ebuf_append_u16_be(buf,info->tftp_blknum);
+ udp_send(info->tftp_socket,buf,info->tftp_ipaddr);
+
+ /*
+ * Wait for some response, retransmitting as necessary
+ */
+
+ /* Foxconn add start by Cliff Wang, 03/23/2010 */
+ buf = udp_recv_with_timeout(info->tftp_socket,tftp_recv_timeout);
+ // buf = udp_recv_with_timeout(info->tftp_socket,TFTP_RECV_TIMEOUT);
+ /* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+ if (buf == NULL) continue;
+
+ /*
+ * Got a response, make sure it's right
+ */
+
+ ebuf_get_u16_be(buf,cmd);
+ if (cmd != TFTP_OP_DATA) {
+ udp_free(buf);
+ continue;
+ }
+
+ ebuf_get_u16_be(buf,block);
+ if (block != (info->tftp_blknum+1)) {
+ udp_free(buf);
+ continue;
+ }
+
+ /*
+ * It's the correct response. Copy the user data
+ */
+
+ info->tftp_blknum = block;
+ info->tftp_blklen = ebuf_length(buf);
+ ebuf_get_bytes(buf,info->tftp_data,ebuf_length(buf));
+ udp_free(buf);
+ break;
+ }
+
+ /*
+ * If the block is less than 512 bytes long, it's the EOF block.
+ */
+
+ if (retries == TFTP_MAX_RETRIES) {
+ info->tftp_error = 1;
+ return CFE_ERR_TIMEOUT;
+ }
+
+ if (info->tftp_blklen < TFTP_BLOCKSIZE) {
+ info->tftp_lastblock = 1; /* EOF */
+ }
+
+ return 0;
+}
+
+/* *********************************************************************
+ * _tftp_writemore(info)
+ *
+ * Write the next block of the file, sending the data from our
+ * holding buffer. Note that the holding buffer must be full
+ * or else we consider this to be an EOF.
+ *
+ * Input parameters:
+ * info - TFTP information
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int _tftp_writemore(tftp_info_t *info)
+{
+ ebuf_t *buf;
+ uint16_t cmd,block,error;
+ int retries;
+
+ /*
+ * If we've already written the last block, there is no more
+ */
+
+ if (info->tftp_lastblock) return 1;
+ if (info->tftp_error) return CFE_ERR_TIMEOUT;
+
+ /*
+ * Otherwise, send a block
+ */
+
+ for (retries = 0; retries < TFTP_MAX_RETRIES; retries++) {
+
+ buf = udp_alloc();
+ if (!buf) return -1;
+
+ /*
+ * Send the data
+ */
+
+ ebuf_append_u16_be(buf,TFTP_OP_DATA);
+ ebuf_append_u16_be(buf,info->tftp_blknum);
+ ebuf_append_bytes(buf,info->tftp_data,info->tftp_blklen);
+ udp_send(info->tftp_socket,buf,info->tftp_ipaddr);
+
+ /*
+ * Wait for some response, retransmitting as necessary
+ */
+
+ /* Foxconn add start by Cliff Wang, 03/23/2010 */
+ buf = udp_recv_with_timeout(info->tftp_socket, tftp_recv_timeout);
+ // buf = udp_recv_with_timeout(info->tftp_socket,TFTP_RECV_TIMEOUT);
+ /* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+ if (buf == NULL) continue;
+
+ /*
+ * Got a response, make sure it's right
+ */
+
+ ebuf_get_u16_be(buf,cmd);
+
+ if (cmd == TFTP_OP_ERROR) {
+ /*
+ * Process the error return (XXX: remove xprintf here)
+ */
+ ebuf_get_u16_be(buf,error);
+ xprintf("TFTP write error %d: %s\n",error,ebuf_ptr(buf));
+ info->tftp_error = 1;
+ info->tftp_lastblock = 1;
+ udp_free(buf);
+ return CFE_ERR_IOERR;
+ }
+
+ if (cmd != TFTP_OP_ACK) {
+ udp_free(buf);
+ continue;
+ }
+
+ ebuf_get_u16_be(buf,block);
+ if (block != (info->tftp_blknum)) {
+ udp_free(buf);
+ continue;
+ }
+
+ /*
+ * It's the correct response. Update the block #
+ */
+
+ info->tftp_blknum++;
+ if (info->tftp_blklen != TFTP_BLOCKSIZE) info->tftp_lastblock = 1;
+ udp_free(buf);
+ break;
+ }
+
+ /*
+ * If we had some failure, mark the stream with an error
+ */
+
+ if (retries == TFTP_MAX_RETRIES) {
+ info->tftp_error = 1;
+ return CFE_ERR_TIMEOUT;
+ }
+
+ return 0;
+}
+
+/* Foxconn add start by Cliff Wang, 03/23/2010 */
+static int _tftpd_open(tftp_info_t *info,char *hostname,char *filename,int mode)
+{
+ ebuf_t *buf = NULL;
+ uint16_t type;
+ int res;
+ int retries;
+ char ch = 0;
+
+ /*
+ * * Open a UDP socket
+ * */
+
+ info->tftp_socket = udp_socket(UDP_PROTO_TFTP);
+ info->tftp_lastblock = 0;
+ info->tftp_error = 0;
+ info->tftp_filemode = mode;
+
+ /*
+ * * Listen for requests
+ * */
+
+ res = udp_bind(info->tftp_socket,UDP_PROTO_TFTP);
+ if (res < 0) return res;
+
+ res = CFE_ERR_TIMEOUT;
+
+ for (retries = 0; retries < tftp_max_retries; retries++) {
+ while (console_status()) {
+ console_read(&ch,1);
+ if (ch == 3) break;
+ }
+
+ if (ch == 3) {
+ res = CFE_ERR_INTR;
+ break;
+ }
+
+ buf = udp_recv_with_timeout(info->tftp_socket,tftp_recv_timeout);
+ if (buf == NULL) continue;
+
+ /*
+ * * Process the request
+ * */
+
+ ebuf_get_u16_be(buf,type);
+
+ switch (type) {
+ case TFTP_OP_RRQ:
+ udp_connect(info->tftp_socket,(uint16_t) buf->eb_usrdata);
+ memcpy(info->tftp_ipaddr,buf->eb_usrptr,IP_ADDR_LEN);
+ info->tftp_blknum = 1;
+ info->tftp_blklen = 0;
+ res = 0;
+ break;
+
+ case TFTP_OP_WRQ:
+ udp_connect(info->tftp_socket,(uint16_t) buf->eb_usrdata);
+ memcpy(info->tftp_ipaddr,buf->eb_usrptr,IP_ADDR_LEN);
+ info->tftp_blknum = 0;
+ res = _tftp_readmore(info);
+ break;
+
+ default:
+ /*
+ * aren't expecting any of these messages
+ * */
+ res = CFE_ERR_PROTOCOLERR;
+ break;
+ }
+
+ udp_free(buf);
+ break;
+ }
+
+ if (res) {
+ udp_close(info->tftp_socket);
+ info->tftp_socket = -1;
+ }
+
+ return res;
+}
+
+
+/* *********************************************************************
+ * _tftp_close(info)
+ *
+ * Close a TFTP file. There are two cases for what we do
+ * here. If we're closing the file mid-stream, send an error
+ * packet to tell the host we're getting out early. Otherwise,
+ * just ack the final packet and the connection will close
+ * gracefully.
+ *
+ * Input parameters:
+ * info - TFTP info
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+static int _tftp_close(tftp_info_t *info)
+{
+ ebuf_t *buf;
+ const char *emsg = "transfer cancelled"; /* some error message */
+
+ if (info->tftp_socket == -1) return 0;
+
+ if (info->tftp_filemode == FILE_MODE_READ) {
+ buf = udp_alloc();
+ if (buf) {
+ /* If we're on the EOF packet, just send an ack */
+ if (info->tftp_lastblock) {
+ ebuf_append_u16_be(buf,TFTP_OP_ACK);
+ ebuf_append_u16_be(buf,info->tftp_blknum);
+ }
+ else {
+ ebuf_append_u16_be(buf,TFTP_OP_ERROR);
+ ebuf_append_u16_be(buf,TFTP_ERR_DISKFULL);
+ ebuf_append_bytes(buf,emsg,strlen(emsg)+1);
+ }
+ udp_send(info->tftp_socket,buf,info->tftp_ipaddr);
+ }
+ }
+ else {
+ /* Just flush out the remaining write data, if any */
+ _tftp_writemore(info);
+ }
+
+ udp_close(info->tftp_socket);
+ info->tftp_socket = -1;
+ return 0;
+}
+
+
+
+/* *********************************************************************
+ * tftp_fileop_init(fsctx,device)
+ *
+ * Create a file system device context for the TFTP service
+ *
+ * Input parameters:
+ * fsctx - location to place context information
+ * device - underlying device (unused)
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int tftp_fileop_init(void **fsctx,void *dev)
+{
+ void *ref;
+
+ ref = KMALLOC(sizeof(tftp_fsctx_t),0);
+
+ if (!ref) return CFE_ERR_NOMEM;
+ *fsctx = ref;
+ return 0;
+}
+
+/* *********************************************************************
+ * tftp_fileop_open(ref,fsctx,filename,mode)
+ *
+ * This is the filesystem entry point for opening a TFTP file.
+ * Allocate a tftp_info structure, open the TFTP file, and
+ * return a handle.
+ *
+ * Input parameters:
+ * ref - location to place reference data (the TFTP structure)
+ * fsctx - filesystem context
+ * filename - name of remote file to open
+ * mode - FILE_MODE_READ or FILE_MODE_WRITE
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int tftp_fileop_open(void **ref,void *fsctx,char *filename,int mode)
+{
+ tftp_info_t *info;
+ char *host;
+ char *file;
+ int res;
+
+ if ((mode != FILE_MODE_READ) && (mode != FILE_MODE_WRITE)) {
+ /* must be either read or write, not both */
+ return CFE_ERR_UNSUPPORTED;
+ }
+
+ /* Allocate the tftp info structure */
+
+ info = KMALLOC(sizeof(tftp_info_t),0);
+ if (!info) {
+ return CFE_ERR_NOMEM;
+ }
+
+
+ info->tftp_filename = lib_strdup(filename);
+ if (!info->tftp_filename) {
+ KFREE(info);
+ return CFE_ERR_NOMEM;
+ }
+
+ lib_chop_filename(info->tftp_filename,&host,&file);
+
+ /* Open the file */
+ /* Foxconn add start by Cliff Wang, 03/23/2010 */
+ if (!*host && !*file) {
+ /* TFTP server if hostname and filename are not specified */
+ res = _tftpd_open(info,host,file,mode);
+ } else {
+ res = _tftp_open(info,host,file,mode);
+ }
+ /* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+ if (res == 0) {
+ info->tftp_blkoffset = 0;
+ info->tftp_fileoffset = 0;
+ *ref = info;
+ }
+ else {
+ KFREE(info->tftp_filename);
+ KFREE(info);
+ *ref = NULL;
+ }
+ return res;
+}
+
+/* *********************************************************************
+ * tftp_fileop_read(ref,buf,len)
+ *
+ * Read some bytes from the remote TFTP file. Do this by copying
+ * data from the block buffer, and reading more data from the
+ * remote file as necessary.
+ *
+ * Input parameters:
+ * ref - tftp_info structure
+ * buf - destination buffer address (NULL to read data and
+ * not copy it anywhere)
+ * len - number of bytes to read
+ *
+ * Return value:
+ * number of bytes read, 0 for EOF, <0 if an error occured.
+ ********************************************************************* */
+
+static int tftp_fileop_read(void *ref,uint8_t *buf,int len)
+{
+ tftp_info_t *info = (tftp_info_t *) ref;
+ int copied = 0;
+ int amtcopy;
+ int res;
+
+ if (info->tftp_error) return CFE_ERR_IOERR;
+ if (info->tftp_filemode == FILE_MODE_WRITE) return CFE_ERR_UNSUPPORTED;
+
+ while (len) {
+
+ if (info->tftp_blkoffset >= info->tftp_blklen) break;
+ amtcopy = len;
+
+ if (amtcopy > (info->tftp_blklen-info->tftp_blkoffset)) {
+ amtcopy = (info->tftp_blklen-info->tftp_blkoffset);
+ }
+
+ if (buf) {
+ memcpy(buf,&(info->tftp_data[info->tftp_blkoffset]),amtcopy);
+ buf += amtcopy;
+ }
+
+ info->tftp_blkoffset += amtcopy;
+ len -= amtcopy;
+ info->tftp_fileoffset += amtcopy;
+ copied += amtcopy;
+
+ if (info->tftp_blkoffset >= info->tftp_blklen) {
+ res = _tftp_readmore(info);
+ if (res != 0) break;
+ info->tftp_blkoffset = 0;
+ }
+ }
+
+ return copied;
+}
+
+/* *********************************************************************
+ * tftp_fileop_write(ref,buf,len)
+ *
+ * Write some bytes to the remote TFTP file. Do this by copying
+ * data to the block buffer, and writing data to the
+ * remote file as necessary.
+ *
+ * Input parameters:
+ * ref - tftp_info structure
+ * buf - source buffer address
+ * len - number of bytes to write
+ *
+ * Return value:
+ * number of bytes written, 0 for EOF, <0 if an error occured.
+ ********************************************************************* */
+
+static int tftp_fileop_write(void *ref,uint8_t *buf,int len)
+{
+ tftp_info_t *info = (tftp_info_t *) ref;
+ int copied = 0;
+ int amtcopy;
+ int res;
+
+ if (info->tftp_error) return CFE_ERR_IOERR;
+ if (info->tftp_filemode == FILE_MODE_READ) return CFE_ERR_UNSUPPORTED;
+
+ while (len) {
+
+ amtcopy = len;
+ if (amtcopy > (TFTP_BLOCKSIZE - info->tftp_blklen)) {
+ amtcopy = (TFTP_BLOCKSIZE - info->tftp_blklen);
+ }
+
+ memcpy(&(info->tftp_data[info->tftp_blklen]),buf,amtcopy);
+ buf += amtcopy;
+
+ info->tftp_blklen += amtcopy;
+ len -= amtcopy;
+ info->tftp_fileoffset += amtcopy;
+ copied += amtcopy;
+
+ if (info->tftp_blklen == TFTP_BLOCKSIZE) {
+ res = _tftp_writemore(info);
+ if (res != 0) {
+ break;
+ }
+ info->tftp_blklen = 0;
+ }
+ }
+
+ return copied;
+}
+
+/* *********************************************************************
+ * tftp_fileop_seek(ref,offset,how)
+ *
+ * Seek within a TFTP file. Note that you can only seek *forward*,
+ * as TFTP doesn't really let you go backwards. (I suppose you
+ * could reopen the file, but thus far nobody needs to go
+ * backwards). You can only seek in a file in read mode.
+ *
+ * Input parameters:
+ * ref - our tftp information
+ * offset - distance to move
+ * how - how to move, (FILE_SEEK_*)
+ *
+ * Return value:
+ * new offset, or <0 if an error occured.
+ ********************************************************************* */
+
+static int tftp_fileop_seek(void *ref,int offset,int how)
+{
+ tftp_info_t *info = (tftp_info_t *) ref;
+ int delta;
+ int startloc;
+ int res;
+
+ if (info->tftp_filemode == FILE_MODE_WRITE) return CFE_ERR_UNSUPPORTED;
+
+ switch (how) {
+ case FILE_SEEK_BEGINNING:
+ startloc = info->tftp_fileoffset;
+ break;
+ case FILE_SEEK_CURRENT:
+ startloc = 0;
+ break;
+ default:
+ startloc = 0;
+ break;
+ }
+
+ delta = offset - startloc;
+ if (delta < 0) {
+ xprintf("Warning: negative seek on tftp file attempted\n");
+ return CFE_ERR_UNSUPPORTED;
+ }
+ res = tftp_fileop_read(ref,NULL,delta);
+ if (res < 0) return res;
+
+ return info->tftp_fileoffset;
+}
+
+
+/* *********************************************************************
+ * tftp_fileop_close(ref)
+ *
+ * Close the TFTP file.
+ *
+ * Input parameters:
+ * ref - our TFTP info
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void tftp_fileop_close(void *ref)
+{
+ tftp_info_t *info = (tftp_info_t *) ref;
+
+ _tftp_close(info);
+
+ KFREE(info->tftp_filename);
+ KFREE(info);
+}
+
+
+/* *********************************************************************
+ * tftp_fileop_uninit(fsctx)
+ *
+ * Uninitialize the filesystem context, freeing allocated
+ * resources.
+ *
+ * Input parameters:
+ * fsctx - our context
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void tftp_fileop_uninit(void *fsctx)
+{
+ KFREE(fsctx);
+}
diff --git a/cfe/cfe/net/net_udp.c b/cfe/cfe/net/net_udp.c
new file mode 100644
index 0000000..968081a
--- /dev/null
+++ b/cfe/cfe/net/net_udp.c
@@ -0,0 +1,637 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * User Datagram Protocol File: net_udp.c
+ *
+ * This module implements the User Datagram Protocol (RFCxxxx)
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_timer.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+
+#include "net_ip.h"
+
+#include "cfe_error.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define UDP_HDR_LENGTH 8
+#define UDP_PORTBASE 1024
+#define UDP_MAX_PORTS 4
+
+/* *********************************************************************
+ * Types
+ ********************************************************************* */
+
+typedef struct udp_port_s udp_port_t;
+
+/*
+ * UDP port structure - describes an open UDP port.
+ */
+
+struct udp_port_s {
+ uint16_t up_destport; /* destination port number */
+ uint16_t up_srcport; /* source port number */
+ queue_t up_rxqueue; /* queue of received packets */
+ int up_maxqueue; /* max # of elements on rx queue */
+ int up_inuse; /* nonzero if port is in use */
+};
+
+
+/*
+ * UDP stack information - describes the entire UDP layer.
+ */
+
+struct udp_info_s {
+ uint16_t ui_portbase;
+ void *ui_ref;
+ ip_info_t *ui_ipinfo;
+ udp_port_t ui_ports[UDP_MAX_PORTS];
+};
+
+/* *********************************************************************
+ * Forward declarations
+ ********************************************************************* */
+
+static int _udp_rx_callback(void *ref,ebuf_t *buf,uint8_t *destaddr,uint8_t *srcaddr);
+
+
+/* *********************************************************************
+ * udp_find_port(info,port)
+ *
+ * Locate an open port. Scan the list of ports looking for one
+ * that is both open and has a matching source port number.
+ *
+ * Input parameters:
+ * info - UDP stack information
+ * port - source port # we're looking for
+ *
+ * Return value:
+ * udp_port_t pointer or NULL if no port was found
+ ********************************************************************* */
+
+static udp_port_t *_udp_find_port(udp_info_t *info,uint16_t port)
+{
+ int idx;
+ udp_port_t *udp = info->ui_ports;
+
+ for (idx = 0; idx < UDP_MAX_PORTS; idx++) {
+ if (udp->up_inuse && (udp->up_srcport == port)) {
+ return udp;
+ }
+ udp++;
+ }
+
+ return NULL;
+}
+
+/* *********************************************************************
+ * _udp_socket(info,port)
+ *
+ * Open a UDP socket. This is an internal function used by
+ * the network API layer.
+ *
+ * Input parameters:
+ * info - UDP stack information
+ * port - port number to open
+ *
+ * Return value:
+ * port number (0 based) or an error code (<0) if an error
+ * occured.
+ ********************************************************************* */
+
+int _udp_socket(udp_info_t *info,uint16_t port)
+{
+ extern int32_t _getticks(void); /* return value of CP0 COUNT */
+ int idx;
+ udp_port_t *udp;
+ uint16_t srcport = UDP_PORTBASE + (_getticks() & 0xFFF);
+
+ while (_udp_find_port(info,srcport)) { /* should always exit */
+ srcport++;
+ if (srcport > (UDP_PORTBASE+4096)) srcport = UDP_PORTBASE;
+ }
+
+ udp = info->ui_ports;
+
+ for (idx = 0; idx < UDP_MAX_PORTS; idx++) {
+ if (!udp->up_inuse) break;
+ udp++;
+ }
+
+ if (idx == UDP_MAX_PORTS) return CFE_ERR_NOHANDLES;
+
+ udp->up_destport = port;
+ udp->up_srcport = srcport;
+ udp->up_maxqueue = 2;
+ udp->up_inuse = TRUE;
+ q_init(&(udp->up_rxqueue));
+
+ return idx;
+}
+
+
+/* *********************************************************************
+ * _udp_close(info,s)
+ *
+ * Internal function to close an open UDP port. This routine is
+ * called by the high-level network API.
+ *
+ * Input parameters:
+ * info - UDP stack information
+ * s - an open UDP socket handle (returned from _udp_open)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void _udp_close(udp_info_t *info,int s)
+{
+ udp_port_t *udp = &(info->ui_ports[s]);
+ ebuf_t *buf;
+
+ while ((buf = (ebuf_t *) q_deqnext(&(udp->up_rxqueue)))) {
+ _ip_free(info->ui_ipinfo,buf);
+ }
+
+ udp->up_srcport = 0;
+ udp->up_destport = 0;
+ udp->up_maxqueue = 0;
+ udp->up_inuse = FALSE;
+}
+
+/* *********************************************************************
+ * _udp_send(info,s,buf,dest)
+ *
+ * Transmit a UDP datagram. Note that we never send fragmented
+ * datagrams, so all datagrams must be less than the MTU.
+ *
+ * Input parameters:
+ * info - UDP stack information
+ * s - an open UDP socket handle (returned from _udp_open)
+ * buf - an ebuf to send
+ * dest - destination IP address
+ *
+ * Return value:
+ * 0 if packet was sent
+ * else error code
+ ********************************************************************* */
+
+int _udp_send(udp_info_t *info,int s,ebuf_t *buf,uint8_t *dest)
+{
+ udp_port_t *udp = &(info->ui_ports[s]);
+ uint8_t *udphdr;
+ int udplen;
+ uint8_t pseudoheader[12];
+ uint16_t cksum;
+
+ /*
+ * Calculate the length of the IP datagram (includes UDP header)
+ */
+
+ udplen = ebuf_length(buf) + UDP_HDR_LENGTH;
+
+ /*
+ * Build the pseudoheader, which is part of the checksum calculation
+ */
+
+ _ip_getaddr(info->ui_ipinfo,&pseudoheader[0]);
+ memcpy(&pseudoheader[4],dest,IP_ADDR_LEN);
+ pseudoheader[8] = 0;
+ pseudoheader[9] = IPPROTO_UDP;
+ pseudoheader[10] = (udplen >> 8) & 0xFF;
+ pseudoheader[11] = (udplen & 0xFF);
+
+ /*
+ * Back up and build the actual UDP header in the packet
+ */
+
+ ebuf_seek(buf,-UDP_HDR_LENGTH);
+ udphdr = ebuf_ptr(buf);
+
+ ebuf_put_u16_be(buf,udp->up_srcport);
+ ebuf_put_u16_be(buf,udp->up_destport);
+ ebuf_put_u16_be(buf,udplen);
+ ebuf_put_u16_be(buf,0);
+
+ ebuf_prepend(buf,UDP_HDR_LENGTH);
+
+ /*
+ * Checksum the packet and insert the checksum into the header
+ */
+
+ cksum = ip_chksum(0,pseudoheader,sizeof(pseudoheader));
+ cksum = ip_chksum(cksum,udphdr,udplen);
+ cksum = ~cksum;
+ if (cksum == 0) cksum = 0xFFFF;
+ udphdr[6] = (cksum >> 8) & 0xFF;
+ udphdr[7] = (cksum & 0xFF);
+
+ /*
+ * Off it goes!
+ */
+
+ _ip_send(info->ui_ipinfo,buf,dest,IPPROTO_UDP);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * _udp_bind(info,s,port)
+ *
+ * Bind a UDP socket to a particular port number. Basically,
+ * all this means is we set the "source" port number.
+ *
+ * Input parameters:
+ * info - UDP stack information
+ * s - an open UDP socket (from _udp_open)
+ * port - port number to assign to the UDP socket
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+int _udp_bind(udp_info_t *info,int s,uint16_t port)
+{
+ udp_port_t *udp = &(info->ui_ports[s]);
+
+ if (_udp_find_port(info,port)) return CFE_ERR_ALREADYBOUND;
+
+ udp->up_srcport = port;
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * _udp_connect(info,s,port)
+ *
+ * "connect" a UDP socket to a particular port number. Basically,
+ * this just sets the "destination" port number. It is used for
+ * protocols like TFTP where the destination port number changes
+ * after the port is open.
+ *
+ * Input parameters:
+ * info - UDP stack information
+ * s - an open UDP socket (from _udp_open)
+ * port - port number to assign to the UDP socket
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int _udp_connect(udp_info_t *info,int s,uint16_t port)
+{
+ udp_port_t *udp = &(info->ui_ports[s]);
+
+ udp->up_destport = port;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * _udp_rx_callback(ref,buf,destaddr,srcaddr)
+ *
+ * Receive callback routine from the IP layer. When an IP
+ * packet of protocol type "UDP" is received, this routine gets
+ * called.
+ *
+ * Input parameters:
+ * ref - reference data (pointer to our UDP stack info)
+ * buf - the ebuf, currently pointing at the UDP header
+ * destaddr - the destination IP address (usually our IP address)
+ * srcaddr - the source IP address
+ *
+ * Return value:
+ * ETH_KEEP to keep (not deallocate) the packet
+ * ETH_DROP to deallocate the packet.
+ ********************************************************************* */
+
+static int _udp_rx_callback(void *ref,ebuf_t *buf,uint8_t *destaddr,uint8_t *srcaddr)
+{
+ uint8_t pseudoheader[12];
+ int udplen;
+ uint16_t calccksum;
+ uint16_t origcksum;
+ uint8_t *udphdr;
+ uint16_t srcport;
+ uint16_t dstport;
+ uint16_t udplen2;
+ udp_port_t *udp;
+ udp_info_t *info = (udp_info_t *) ref;
+
+
+
+ /*
+ * get a pointer to the UDP header
+ */
+
+ udplen = ebuf_length(buf);
+ udphdr = ebuf_ptr(buf);
+
+ /*
+ * see if we are checking checksums (cksum field != 0)
+ */
+
+ if ((udphdr[6] | udphdr[7]) != 0) {
+
+ /*
+ * construct the pseudoheader for the cksum calculation
+ */
+
+ memcpy(&pseudoheader[0],srcaddr,IP_ADDR_LEN);
+ memcpy(&pseudoheader[4],destaddr,IP_ADDR_LEN);
+ pseudoheader[8] = 0;
+ pseudoheader[9] = IPPROTO_UDP;
+ pseudoheader[10] = (udplen >> 8) & 0xFF;
+ pseudoheader[11] = (udplen & 0xFF);
+
+ origcksum = ((uint16_t) udphdr[6] << 8) | (uint16_t) udphdr[7];
+ udphdr[6] = udphdr[7] = 0;
+
+ calccksum = ip_chksum(0,pseudoheader,sizeof(pseudoheader));
+ calccksum = ip_chksum(calccksum,udphdr,udplen);
+ if (calccksum != 0xffff) {
+ calccksum = ~calccksum;
+ }
+
+ if (calccksum != origcksum) {
+ return ETH_DROP;
+ }
+ }
+
+ /* Read the other UDP header fields from the packet */
+
+ ebuf_get_u16_be(buf,srcport);
+ ebuf_get_u16_be(buf,dstport);
+ ebuf_get_u16_be(buf,udplen2);
+ ebuf_skip(buf,2);
+
+ /*
+ * It's no good if the lengths don't match. The length
+ * reported by IP should be the length in the UDP header + 8
+ */
+
+ if (udplen2 != (uint16_t) udplen) {
+ return ETH_DROP;
+ }
+
+ /*
+ * Okay, start looking for a matching port
+ */
+
+ udp = _udp_find_port(info,dstport);
+ if (!udp) {
+ return ETH_DROP; /* drop packet if no matching port */
+ /* XXX should send ICMP message here */
+ }
+
+ buf->eb_usrdata = (int) srcport;
+ buf->eb_usrptr = srcaddr;
+
+ /*
+ * Drop packet if queue is full
+ */
+
+ if (q_count(&(udp->up_rxqueue)) >= udp->up_maxqueue) {
+ return ETH_DROP;
+ }
+
+ /*
+ * Add to receive queue
+ */
+
+ ebuf_setlength(buf,udplen2-UDP_HDR_LENGTH);
+ q_enqueue(&(udp->up_rxqueue),(queue_t *) buf);
+
+ return ETH_KEEP;
+}
+
+
+/* *********************************************************************
+ * _udp_recv(info,s)
+ *
+ * Receive a packet from the specified UDP socket.
+ *
+ * Input parameters:
+ * info - UDP stack information
+ * s - an open UDP socket handle (from _udp_open)
+ *
+ * Return value:
+ * an ebuf, or NULL if no packets have been received.
+ ********************************************************************* */
+
+ebuf_t *_udp_recv(udp_info_t *info,int s)
+{
+ ebuf_t *buf;
+ udp_port_t *udp = &(info->ui_ports[s]);
+
+ buf = (ebuf_t *) q_deqnext(&(udp->up_rxqueue));
+
+ return buf;
+}
+
+
+/* *********************************************************************
+ * _udp_init(ipi,ref)
+ *
+ * Initialize the UDP module. This routine registers our
+ * protocol with the IP layer.
+ *
+ * Input parameters:
+ * ipi - IP information (including our IP address, etc.)
+ * ref - reference data, stored in our UDP stack structure
+ *
+ * Return value:
+ * udp_info_t (allocated) or NULL if something went wrong.
+ ********************************************************************* */
+
+udp_info_t *_udp_init(ip_info_t *ipi,void *ref)
+{
+ udp_info_t *info;
+ udp_port_t *udp;
+ int idx;
+
+ /*
+ * Allocate some memory for our structure
+ */
+
+ info = KMALLOC(sizeof(udp_info_t),0);
+
+ if (info == NULL) return NULL;
+
+ memset(info,0,sizeof(udp_info_t));
+
+ /*
+ * Fill in the fields.
+ */
+
+ info->ui_ref = ref;
+ info->ui_ipinfo = ipi;
+ udp = info->ui_ports;
+ for (idx = 0; idx < UDP_MAX_PORTS; idx++) {
+ udp->up_inuse = FALSE;
+ q_init(&(udp->up_rxqueue));
+ udp++;
+ }
+
+ /*
+ * Register our protocol with IP
+ */
+
+ _ip_register(ipi,IPPROTO_UDP,_udp_rx_callback,info);
+
+ return info;
+}
+
+
+/* *********************************************************************
+ * _udp_uninit(info)
+ *
+ * Uninitialize the UDP module, deregistering ourselves from the
+ * IP layer.
+ *
+ * Input parameters:
+ * info - UDP stack information
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void _udp_uninit(udp_info_t *info)
+{
+ int idx;
+ udp_port_t *udp;
+ ebuf_t *buf;
+
+ /*
+ * Unregister from IP
+ */
+
+ _ip_deregister(info->ui_ipinfo,IPPROTO_UDP);
+
+ /*
+ * Free up any packets that were waiting
+ */
+
+ udp = info->ui_ports;
+ for (idx = 0; idx < UDP_MAX_PORTS; idx++) {
+ if (udp->up_inuse) {
+ while ((buf = (ebuf_t *) q_deqnext(&(udp->up_rxqueue)))) {
+ _ip_free(info->ui_ipinfo,buf);
+ }
+ }
+ udp++;
+ }
+
+ /*
+ * Free the stack info
+ */
+
+ KFREE(info);
+}
+
+/* *********************************************************************
+ * _udp_alloc(info)
+ *
+ * Allocate a buffer for use with UDP. This routine obtains an
+ * ebuf and adjusts its header to include room for the UDP
+ * header.
+ *
+ * Input parameters:
+ * info - UDP stack information
+ *
+ * Return value:
+ * ebuf, or NULL if there are none left
+ ********************************************************************* */
+
+ebuf_t *_udp_alloc(udp_info_t *info)
+{
+ ebuf_t *buf;
+
+ /*
+ * Get an ebuf
+ */
+
+ buf = _ip_alloc(info->ui_ipinfo);
+
+ if (!buf) return NULL;
+
+ /*
+ * make room for the udp header
+ */
+
+ ebuf_seek(buf,UDP_HDR_LENGTH);
+ ebuf_setlength(buf,0);
+
+ return buf;
+}
+
+/* *********************************************************************
+ * _udp_free(info,buf)
+ *
+ * Return an ebuf to the pool.
+ *
+ * Input parameters:
+ * info - UDP stack info
+ * buf - an ebuf
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void _udp_free(udp_info_t *info,ebuf_t *buf)
+{
+ _ip_free(info->ui_ipinfo,buf);
+}
diff --git a/cfe/cfe/pccons/Makefile b/cfe/cfe/pccons/Makefile
new file mode 100644
index 0000000..09b8610
--- /dev/null
+++ b/cfe/cfe/pccons/Makefile
@@ -0,0 +1,3 @@
+
+CFLAGS += -DCFG_VGACONSOLE=1
+ALLOBJS += vgainit.o vga_subr.o kbd_subr.o x86mem.o dev_pcconsole.o dev_pcconsole2.o
diff --git a/cfe/cfe/pccons/README b/cfe/cfe/pccons/README
new file mode 100644
index 0000000..0160ad5
--- /dev/null
+++ b/cfe/cfe/pccons/README
@@ -0,0 +1,19 @@
+
+This directory contains "PC Console" routines, to enable the
+SWARM board to use PC-style devices for its console. In
+particular, it contains the code to use the X86 emulator
+to initialize the VGA, and code to map scan codes to
+ASCII characters for a PC keyboard.
+
+What is this good for, you ask? Just for fun, mostly. Many of
+us have had this screwy notion that a SWARM could be used as
+a Linux "workstation" if we could get VGA support and USB
+keyboards implemented (oh, yeah, and there's this whole
+matter of PC console support in Linux, and X, and ...).
+
+Like the USB host stack, this is among the least-supported
+portions of CFE. If you find it useful, great! If it doesn't
+work or build properly, let us know, but we may not get to fixing
+it right away.
+
+
diff --git a/cfe/cfe/pccons/dev_pcconsole.c b/cfe/cfe/pccons/dev_pcconsole.c
new file mode 100644
index 0000000..fe85eca
--- /dev/null
+++ b/cfe/cfe/pccons/dev_pcconsole.c
@@ -0,0 +1,339 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * PC Console driver File: dev_pcconsole.c
+ *
+ * A console driver for a PC-style keyboard and mouse
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+
+#include "sbmips.h"
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+
+#include "lib_physio.h"
+
+#include "kbd_subr.h"
+#include "vga_subr.h"
+
+#include "bsp_config.h"
+#include "pcireg.h"
+#include "pcivar.h"
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define KBD_RXFULL 1 /* bit set if kb has data */
+#define KBD_TXFULL 2 /* bit set if we can send cmd */
+#define VGA_TEXTBUF_COLOR 0xB8000 /* VGA frame buffer */
+
+#if defined(_P5064_) || defined(_P6064_)
+ #define PCI_MEM_SPACE 0x10000000 /* 128MB: s/w configurable */
+ #define __ISAaddr(addr) ((physaddr_t)(PCI_MEM_SPACE+(addr)))
+#else
+ #define __ISAaddr(addr) ((physaddr_t)0x40000000+(addr))
+#endif
+
+#define cpu_isamap(x,y) __ISAaddr(x)
+
+/* *********************************************************************
+ * Forward references
+ ********************************************************************* */
+
+static void pcconsole_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+
+static int pcconsole_open(cfe_devctx_t *ctx);
+static int pcconsole_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int pcconsole_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int pcconsole_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int pcconsole_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int pcconsole_close(cfe_devctx_t *ctx);
+static void pcconsole_poll(cfe_devctx_t *ctx,int64_t ticks);
+
+const static cfe_devdisp_t pcconsole_dispatch = {
+ pcconsole_open,
+ pcconsole_read,
+ pcconsole_inpstat,
+ pcconsole_write,
+ pcconsole_ioctl,
+ pcconsole_close,
+ pcconsole_poll,
+ NULL
+};
+
+const cfe_driver_t pcconsole = {
+ "PC Console",
+ "pcconsole",
+ CFE_DEV_SERIAL,
+ &pcconsole_dispatch,
+ pcconsole_probe
+};
+
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+
+typedef struct pcconsole_s {
+ vga_term_t vga;
+ keystate_t ks;
+ uint32_t kbd_status;
+ uint32_t kbd_data;
+} pcconsole_t;
+
+
+/* *********************************************************************
+ * pcconsole_poll(ctx,ticks)
+ *
+ * Poll routine - check for new keyboard events
+ *
+ * Input parameters:
+ * ctx - device context
+ * ticks - current time
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+static void pcconsole_poll(cfe_devctx_t *ctx,int64_t ticks)
+{
+ pcconsole_t *softc = ctx->dev_softc;
+ uint8_t status;
+ uint8_t b;
+
+ status = inb(softc->kbd_status);
+
+ if (status & KBD_RXFULL) {
+ b = inb(softc->kbd_data);
+ kbd_doscan(&(softc->ks),b);
+ }
+}
+
+/* *********************************************************************
+ * pcconsole_waitcmdready(softc)
+ *
+ * Wait for the keyboard to be ready to accept a command
+ *
+ * Input parameters:
+ * softc - console structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void pcconsole_waitcmdready(pcconsole_t *softc)
+{
+ uint8_t status;
+ uint8_t data;
+
+ for (;;) {
+ status = inb(softc->kbd_status); /* read status */
+ if (status & KBD_RXFULL) {
+ data = inb(softc->kbd_data); /* get data */
+ kbd_doscan(&(softc->ks),data); /* process scan codes */
+ }
+ if (!(status & KBD_TXFULL)) break; /* stop when kbd ready */
+ }
+}
+
+
+/* *********************************************************************
+ * pcconsole_setleds(ks,leds)
+ *
+ * Callback from the keyboard routines for setting the LEDS
+ *
+ * Input parameters:
+ * ks - keyboard state
+ * leds - new LED state
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int pcconsole_setleds(keystate_t *ks,int leds)
+{
+ pcconsole_t *softc = kbd_getref(ks);
+
+ pcconsole_waitcmdready(softc);
+ outb(softc->kbd_data,KBDCMD_SETLEDS);
+ pcconsole_waitcmdready(softc);
+ outb(softc->kbd_data,(leds & 7));
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * pcconsole_probe(drv,probe_a,probe_b,probe_ptr)
+ *
+ * Probe routine. This routine sets up the pcconsole device
+ *
+ * Input parameters:
+ * drv - driver structure
+ * probe_a
+ * probe_b
+ * probe_ptr
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void pcconsole_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ pcconsole_t *softc;
+ char descr[80];
+ volatile uint8_t *isamem;
+
+ /*
+ * probe_a is
+ * probe_b is
+ * probe_ptr is
+ */
+
+ softc = (pcconsole_t *) KMALLOC(sizeof(pcconsole_t),0);
+ if (softc) {
+ /*
+ * XXX This should not be hardwired.
+ */
+ softc->kbd_status = 0x64;
+ softc->kbd_data = 0x60;
+ kbd_init(&(softc->ks),pcconsole_setleds,softc);
+
+ /*
+ * XXX this should not be hardwired
+ */
+ isamem = (volatile uint8_t *) ((uintptr_t)cpu_isamap(0,1024*1024));
+ vga_init(&(softc->vga),__ISAaddr(VGA_TEXTBUF_COLOR),outb);
+
+ xsprintf(descr,"%s",drv->drv_description,probe_a,probe_b);
+ cfe_attach(drv,softc,NULL,descr);
+ }
+
+}
+
+
+static int pcconsole_open(cfe_devctx_t *ctx)
+{
+ pcconsole_t *softc = ctx->dev_softc;
+
+ outb(softc->kbd_data,KBDCMD_RESET); /* reset keyboard */
+ kbd_init(&(softc->ks),pcconsole_setleds,softc);
+ vga_clear(&(softc->vga));
+ vga_setcursor(&(softc->vga),0,0);
+
+ return 0;
+}
+
+static int pcconsole_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ pcconsole_t *softc = ctx->dev_softc;
+ unsigned char *bptr;
+ int blen;
+
+ pcconsole_poll(ctx,0);
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+
+ while ((blen > 0) && (kbd_inpstat(&(softc->ks)))) {
+ *bptr++ = (kbd_read(&(softc->ks)) & 0xFF);
+ blen--;
+ }
+
+ buffer->buf_retlen = buffer->buf_length - blen;
+ return 0;
+}
+
+static int pcconsole_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
+{
+ pcconsole_t *softc = ctx->dev_softc;
+
+ pcconsole_poll(ctx,0);
+
+ inpstat->inp_status = kbd_inpstat(&(softc->ks)) ? 1 : 0;
+
+ return 0;
+}
+
+static int pcconsole_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ pcconsole_t *softc = ctx->dev_softc;
+ unsigned char *bptr;
+ int blen;
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+
+ vga_writestr(&(softc->vga),bptr,7,blen);
+
+ buffer->buf_retlen = buffer->buf_length;
+ return 0;
+}
+
+static int pcconsole_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+/* pcconsole_t *softc = ctx->dev_softc;*/
+
+ return -1;
+}
+
+static int pcconsole_close(cfe_devctx_t *ctx)
+{
+/* pcconsole_t *softc = ctx->dev_softc;*/
+
+ return 0;
+}
+
+
diff --git a/cfe/cfe/pccons/dev_pcconsole2.c b/cfe/cfe/pccons/dev_pcconsole2.c
new file mode 100644
index 0000000..e078c13
--- /dev/null
+++ b/cfe/cfe/pccons/dev_pcconsole2.c
@@ -0,0 +1,298 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * PC Console driver File: dev_pcconsole2.c
+ *
+ * A console driver for a PC-style keyboard and mouse
+ *
+ * This version is for USB keyboards. Someday we'll consolidate
+ * everything.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+
+#include "sbmips.h"
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_timer.h"
+
+#include "lib_physio.h"
+
+#include "vga_subr.h"
+
+#include "bsp_config.h"
+#include "pcireg.h"
+#include "pcivar.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define KBD_RXFULL 1 /* bit set if kb has data */
+#define KBD_TXFULL 2 /* bit set if we can send cmd */
+#define VGA_TEXTBUF_COLOR 0xB8000 /* VGA frame buffer */
+
+/* XXX SB1250 specific */
+#define __ISAaddr(x)(0x40000000+(x))
+
+/* *********************************************************************
+ * Forward references
+ ********************************************************************* */
+
+int pcconsole_enqueue(uint8_t ch);
+
+static void pcconsole_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+
+static int pcconsole_open(cfe_devctx_t *ctx);
+static int pcconsole_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int pcconsole_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int pcconsole_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int pcconsole_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int pcconsole_close(cfe_devctx_t *ctx);
+static void pcconsole_poll(cfe_devctx_t *ctx,int64_t ticks);
+
+const static cfe_devdisp_t pcconsole_dispatch = {
+ pcconsole_open,
+ pcconsole_read,
+ pcconsole_inpstat,
+ pcconsole_write,
+ pcconsole_ioctl,
+ pcconsole_close,
+ pcconsole_poll,
+ NULL
+};
+
+const cfe_driver_t pcconsole2 = {
+ "PC Console (USB)",
+ "pcconsole",
+ CFE_DEV_SERIAL,
+ &pcconsole_dispatch,
+ pcconsole_probe
+};
+
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+#define KBD_QUEUE_LEN 32
+
+typedef struct pcconsole_s {
+ vga_term_t vga;
+ int kbd_in;
+ int kbd_out;
+ uint8_t kbd_data[KBD_QUEUE_LEN];
+} pcconsole_t;
+
+static pcconsole_t *pcconsole_current = NULL;
+
+/* *********************************************************************
+ * pcconsole_poll(ctx,ticks)
+ *
+ * Poll routine - check for new keyboard events
+ *
+ * Input parameters:
+ * ctx - device context
+ * ticks - current time
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+static void pcconsole_poll(cfe_devctx_t *ctx,int64_t ticks)
+{
+ /* No polling needed, USB will do the work for us */
+}
+
+
+
+/* *********************************************************************
+ * pcconsole_probe(drv,probe_a,probe_b,probe_ptr)
+ *
+ * Probe routine. This routine sets up the pcconsole device
+ *
+ * Input parameters:
+ * drv - driver structure
+ * probe_a
+ * probe_b
+ * probe_ptr
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void pcconsole_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ pcconsole_t *softc;
+ char descr[80];
+
+ /*
+ * probe_a is
+ * probe_b is
+ * probe_ptr is
+ */
+
+ softc = (pcconsole_t *) KMALLOC(sizeof(pcconsole_t),0);
+ if (softc) {
+
+ memset(softc,0,sizeof(pcconsole_t));
+
+ /*
+ * XXX this should not be hardwired
+ */
+ vga_init(&(softc->vga),__ISAaddr(VGA_TEXTBUF_COLOR),outb);
+
+ xsprintf(descr,"%s",drv->drv_description,probe_a,probe_b);
+ cfe_attach(drv,softc,NULL,descr);
+ }
+
+}
+
+
+static int pcconsole_open(cfe_devctx_t *ctx)
+{
+ pcconsole_t *softc = ctx->dev_softc;
+
+ pcconsole_current = softc;
+
+ softc->kbd_in = 0;
+ softc->kbd_out = 0;
+
+ vga_clear(&(softc->vga));
+ vga_setcursor(&(softc->vga),0,0);
+
+ return 0;
+}
+
+static int pcconsole_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ pcconsole_t *softc = ctx->dev_softc;
+ unsigned char *bptr;
+ int blen;
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+
+ while ((blen > 0) && (softc->kbd_in != softc->kbd_out)) {
+ *bptr++ = softc->kbd_data[softc->kbd_out];
+ softc->kbd_out++;
+ if (softc->kbd_out >= KBD_QUEUE_LEN) {
+ softc->kbd_out = 0;
+ }
+ blen--;
+ }
+
+ buffer->buf_retlen = buffer->buf_length - blen;
+ return 0;
+}
+
+static int pcconsole_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
+{
+ pcconsole_t *softc = ctx->dev_softc;
+
+ POLL();
+
+ inpstat->inp_status = (softc->kbd_in != softc->kbd_out);
+
+ return 0;
+}
+
+static int pcconsole_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ pcconsole_t *softc = ctx->dev_softc;
+ unsigned char *bptr;
+ int blen;
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+
+ vga_writestr(&(softc->vga),bptr,7,blen);
+
+ buffer->buf_retlen = buffer->buf_length;
+ return 0;
+}
+
+static int pcconsole_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+/* pcconsole_t *softc = ctx->dev_softc;*/
+
+ return -1;
+}
+
+static int pcconsole_close(cfe_devctx_t *ctx)
+{
+/* pcconsole_t *softc = ctx->dev_softc;*/
+ pcconsole_current = NULL;
+
+ return 0;
+}
+
+/*
+ * Called by USB system to queue characters.
+ */
+int pcconsole_enqueue(uint8_t ch)
+{
+ int newidx;
+
+ if (!pcconsole_current) return -1;
+
+ newidx = pcconsole_current->kbd_in+1;
+ if (newidx >= KBD_QUEUE_LEN) newidx = 0;
+
+ if (newidx == pcconsole_current->kbd_out) return -1;
+
+ pcconsole_current->kbd_data[pcconsole_current->kbd_in] = ch;
+ pcconsole_current->kbd_in = newidx;
+
+ return 0;
+}
diff --git a/cfe/cfe/pccons/kbd_subr.c b/cfe/cfe/pccons/kbd_subr.c
new file mode 100644
index 0000000..860db94
--- /dev/null
+++ b/cfe/cfe/pccons/kbd_subr.c
@@ -0,0 +1,371 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * PC-style keyboard interface File: KBD_SUBR.C
+ *
+ * This module converts a stream of scancodes into ASCII
+ * characters. The scan codes come from a PC-style
+ * keyboard.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+
+#include "kbd_subr.h"
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define FLG_SCROLL 0x0001 /* Toggles: same as bit positions for LEDs! */
+#define FLG_NUM 0x0002
+#define FLG_CAPS 0x0004
+#define FLG_SHIFT 0x0008 /* Shifts */
+#define FLG_CTRL 0x0100
+#define FLG_ALT 0x0200
+#define FLG_FKEY 0x0400 /* function keys */
+#define FLG_NKPD 0x0800 /* numeric keypad */
+#define FLG_ASCII 0x1000 /* regular ASCII character */
+#define FLG_NONE 0x2000
+#define FLG_BREAKBIT 0x80
+
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+#define KC_RESPLEN 4
+typedef struct keycode_s {
+ int kc_type;
+ char kc_normal[KC_RESPLEN];
+ char kc_shifted[KC_RESPLEN];
+ char kc_ctrl[KC_RESPLEN];
+} keycode_t;
+
+
+/* *********************************************************************
+ * Scan code conversion table
+ ********************************************************************* */
+
+static keycode_t scantable[] = {
+ { FLG_NONE, "", "", "" }, /* 0 */
+ { FLG_ASCII, "\033", "\033", "\033" }, /* 1 ESC */
+ { FLG_ASCII, "1", "!", "!" }, /* 2 1 */
+ { FLG_ASCII, "2", "@", "\000" }, /* 3 2 */
+ { FLG_ASCII, "3", "#", "#" }, /* 4 3 */
+ { FLG_ASCII, "4", "$", "$" }, /* 5 4 */
+ { FLG_ASCII, "5", "%", "%" }, /* 6 5 */
+ { FLG_ASCII, "6", "^", "\036" }, /* 7 6 */
+ { FLG_ASCII, "7", "&", "&" }, /* 8 7 */
+ { FLG_ASCII, "8", "*", "\010" }, /* 9 8 */
+ { FLG_ASCII, "9", "(", "(" }, /* 10 9 */
+ { FLG_ASCII, "0", ")", ")" }, /* 11 0 */
+ { FLG_ASCII, "-", "_", "\037" }, /* 12 - */
+ { FLG_ASCII, "=", "+", "+" }, /* 13 = */
+ { FLG_ASCII, "\177", "\177", "\010" }, /* 14 <- */
+ { FLG_ASCII, "\t", "\177\t", "\t" }, /* 15 ->| */
+ { FLG_ASCII, "q", "Q", "\021" }, /* 16 q */
+ { FLG_ASCII, "w", "W", "\027" }, /* 17 w */
+ { FLG_ASCII, "e", "E", "\005" }, /* 18 e */
+ { FLG_ASCII, "r", "R", "\022" }, /* 19 r */
+ { FLG_ASCII, "t", "T", "\024" }, /* 20 t */
+ { FLG_ASCII, "y", "Y", "\031" }, /* 21 y */
+ { FLG_ASCII, "u", "U", "\025" }, /* 22 u */
+ { FLG_ASCII, "i", "I", "\011" }, /* 23 i */
+ { FLG_ASCII, "o", "O", "\017" }, /* 24 o */
+ { FLG_ASCII, "p", "P", "\020" }, /* 25 p */
+ { FLG_ASCII, "[", "{", "\033" }, /* 26 [ */
+ { FLG_ASCII, "]", "}", "\035" }, /* 27 ] */
+ { FLG_ASCII, "\r", "\r", "\n" }, /* 28 ENT */
+ { FLG_CTRL, "", "", "" }, /* 29 CTRL */
+ { FLG_ASCII, "a", "A", "\001" }, /* 30 a */
+ { FLG_ASCII, "s", "S", "\023" }, /* 31 s */
+ { FLG_ASCII, "d", "D", "\004" }, /* 32 d */
+ { FLG_ASCII, "f", "F", "\006" }, /* 33 f */
+ { FLG_ASCII, "g", "G", "\007" }, /* 34 g */
+ { FLG_ASCII, "h", "H", "\010" }, /* 35 h */
+ { FLG_ASCII, "j", "J", "\n" }, /* 36 j */
+ { FLG_ASCII, "k", "K", "\013" }, /* 37 k */
+ { FLG_ASCII, "l", "L", "\014" }, /* 38 l */
+ { FLG_ASCII, ";", ":", ";" }, /* 39 ; */
+ { FLG_ASCII, "'", "\"", "'" }, /* 40 ' */
+ { FLG_ASCII, "`", "~", "`" }, /* 41 ` */
+ { FLG_SHIFT, "", "", "" }, /* 42 SHIFT */
+ { FLG_ASCII, "\\", "|", "\034" }, /* 43 \ */
+ { FLG_ASCII, "z", "Z", "\032" }, /* 44 z */
+ { FLG_ASCII, "x", "X", "\030" }, /* 45 x */
+ { FLG_ASCII, "c", "C", "\003" }, /* 46 c */
+ { FLG_ASCII, "v", "V", "\026" }, /* 47 v */
+ { FLG_ASCII, "b", "B", "\002" }, /* 48 b */
+ { FLG_ASCII, "n", "N", "\016" }, /* 49 n */
+ { FLG_ASCII, "m", "M", "\r" }, /* 50 m */
+ { FLG_ASCII, ",", "<", "<" }, /* 51 , */
+ { FLG_ASCII, ".", ">", ">" }, /* 52 . */
+ { FLG_ASCII, "/", "?", "\037" }, /* 53 / */
+ { FLG_SHIFT, "", "", "" }, /* 54 SHIFT */
+ { FLG_NKPD, "*", "*", "*" }, /* 55 KP* */
+ { FLG_ALT, "", "", "" }, /* 56 ALT */
+ { FLG_ASCII, " ", " ", "\000" }, /* 57 SPC */
+ { FLG_CAPS, "", "", "" }, /* 58 CAPS */
+ { FLG_FKEY, "\033[M", "\033[Y", "\033[k" }, /* 59 f1 */
+ { FLG_FKEY, "\033[N", "\033[Z", "\033[l" }, /* 60 f2 */
+ { FLG_FKEY, "\033[O", "\033[a", "\033[m" }, /* 61 f3 */
+ { FLG_FKEY, "\033[P", "\033[b", "\033[n" }, /* 62 f4 */
+ { FLG_FKEY, "\033[Q", "\033[c", "\033[o" }, /* 63 f5 */
+ { FLG_FKEY, "\033[R", "\033[d", "\033[p" }, /* 64 f6 */
+ { FLG_FKEY, "\033[S", "\033[e", "\033[q" }, /* 65 f7 */
+ { FLG_FKEY, "\033[T", "\033[f", "\033[r" }, /* 66 f8 */
+ { FLG_FKEY, "\033[U", "\033[g", "\033[s" }, /* 67 f9 */
+ { FLG_FKEY, "\033[V", "\033[h", "\033[t" }, /* 68 f10 */
+ { FLG_NUM, "", "", "" }, /* 69 NUMLK */
+ { FLG_SCROLL, "", "", "" }, /* 70 SCRLK */
+ { FLG_NKPD, "7", "\033[H", "7" }, /* 71 KP7 */
+ { FLG_NKPD, "8", "\033[A", "8" }, /* 72 KP8 */
+ { FLG_NKPD, "9", "\033[I", "9" }, /* 73 KP9 */
+ { FLG_NKPD, "-", "-", "-" }, /* 74 KP- */
+ { FLG_NKPD, "4", "\033[D", "4" }, /* 75 KP4 */
+ { FLG_NKPD, "5", "\033[E", "5" }, /* 76 KP5 */
+ { FLG_NKPD, "6", "\033[C", "6" }, /* 77 KP6 */
+ { FLG_NKPD, "+", "+", "+" }, /* 78 KP+ */
+ { FLG_NKPD, "1", "\033[F", "1" }, /* 79 KP1 */
+ { FLG_NKPD, "2", "\033[B", "2" }, /* 80 KP2 */
+ { FLG_NKPD, "3", "\033[G", "3" }, /* 81 KP3 */
+ { FLG_NKPD, "0", "\033[L", "0" }, /* 82 KP0 */
+ { FLG_NKPD, ".", "\177", "." }, /* 83 KP. */
+ { FLG_NONE, "", "", "" }, /* 84 0 */
+ { FLG_NONE, "100", "", "" }, /* 85 0 */
+ { FLG_NONE, "101", "", "" }, /* 86 0 */
+ { FLG_FKEY, "\033[W", "\033[i", "\033[u" }, /* 87 f11 */
+ { FLG_FKEY, "\033[X", "\033[j", "\033[v" }, /* 88 f12 */
+ { FLG_NONE, "102", "", "" }, /* 89 0 */
+ { FLG_NONE, "103", "", "" }, /* 90 0 */
+ { FLG_NONE, "", "", "" }, /* 91 0 */
+ { FLG_NONE, "", "", "" }, /* 92 0 */
+ { FLG_NONE, "", "", "" }, /* 93 0 */
+ { FLG_NONE, "", "", "" }, /* 94 0 */
+ { FLG_NONE, "", "", "" }, /* 95 0 */
+ { FLG_NONE, "", "", "" }, /* 96 0 */
+ { FLG_NONE, "", "", "" }, /* 97 0 */
+ { FLG_NONE, "", "", "" }, /* 98 0 */
+ { FLG_NONE, "", "", "" }, /* 99 0 */
+ { FLG_NONE, "", "", "" }, /* 100 */
+ { FLG_NONE, "", "", "" }, /* 101 */
+ { FLG_NONE, "", "", "" }, /* 102 */
+ { FLG_NONE, "", "", "" }, /* 103 */
+ { FLG_NONE, "", "", "" }, /* 104 */
+ { FLG_NONE, "", "", "" }, /* 105 */
+ { FLG_NONE, "", "", "" }, /* 106 */
+ { FLG_NONE, "", "", "" }, /* 107 */
+ { FLG_NONE, "", "", "" }, /* 108 */
+ { FLG_NONE, "", "", "" }, /* 109 */
+ { FLG_NONE, "", "", "" }, /* 110 */
+ { FLG_NONE, "", "", "" }, /* 111 */
+ { FLG_NONE, "", "", "" }, /* 112 */
+ { FLG_NONE, "", "", "" }, /* 113 */
+ { FLG_NONE, "", "", "" }, /* 114 */
+ { FLG_NONE, "", "", "" }, /* 115 */
+ { FLG_NONE, "", "", "" }, /* 116 */
+ { FLG_NONE, "", "", "" }, /* 117 */
+ { FLG_NONE, "", "", "" }, /* 118 */
+ { FLG_NONE, "", "", "" }, /* 119 */
+ { FLG_NONE, "", "", "" }, /* 120 */
+ { FLG_NONE, "", "", "" }, /* 121 */
+ { FLG_NONE, "", "", "" }, /* 122 */
+ { FLG_NONE, "", "", "" }, /* 123 */
+ { FLG_NONE, "", "", "" }, /* 124 */
+ { FLG_NONE, "", "", "" }, /* 125 */
+ { FLG_NONE, "", "", "" }, /* 126 */
+ { FLG_NONE, "", "", "" }, /* 127 */
+};
+
+
+/* *********************************************************************
+ * KBD_ENQUEUECHAR(ks,ch)
+ *
+ * Put a character on the queue
+ *
+ * Input parameters:
+ * ks - keyboard state
+ * ch - character to enqueue
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void kbd_enqueuechar(keystate_t *ks,char ch)
+{
+ if (((ks->ks_head+1) & (KEYQUEUELEN-1)) == ks->ks_tail) {
+ /* queue is full */
+ return;
+ }
+ ks->ks_queue[ks->ks_head] = ch;
+ ks->ks_head = (ks->ks_head+1) & (KEYQUEUELEN-1);
+}
+
+
+/* *********************************************************************
+ * KBD_DEQUEUECHAR(ks)
+ *
+ * Remove a character from the queue
+ *
+ * Input parameters:
+ * ks - keystate
+ *
+ * Return value:
+ * 0 if no characters in queue
+ * else character from queue
+ ********************************************************************* */
+static int kbd_dequeuechar(keystate_t *ks)
+{
+ char ch;
+
+ if (ks->ks_head == ks->ks_tail) return 0;
+
+ ch = ks->ks_queue[ks->ks_tail];
+ ks->ks_tail = (ks->ks_tail+1) & (KEYQUEUELEN-1);
+ return ch;
+}
+
+/* *********************************************************************
+ * KBD_READ(ks)
+ *
+ * User call to kbd_dequeuechar - remove a character from
+ * the queue.
+ *
+ * Input parameters:
+ * ks - keyboard state
+ *
+ * Return value:
+ * character from queue or 0 if no chars
+ ********************************************************************* */
+
+int kbd_read(keystate_t *ks)
+{
+ return kbd_dequeuechar(ks);
+}
+
+/* *********************************************************************
+ * KBD_INPSTAT(ks)
+ *
+ * Test input status (see if a character is waiting)
+ *
+ * Input parameters:
+ * ks - keyboard state
+ *
+ * Return value:
+ * 0 if no chars waiting, 1 if characters are waiting
+ ********************************************************************* */
+
+int kbd_inpstat(keystate_t *ks)
+{
+ return (ks->ks_head != ks->ks_tail);
+}
+
+
+/* *********************************************************************
+ * KBD_DOSCAN(ks,scan)
+ *
+ * Process a scan code from the keyboard.
+ *
+ * Input parameters:
+ * ks - keyboard state
+ * scan - scan code from the keyboard
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void kbd_doscan(keystate_t *ks,uint8_t scan)
+{
+ int breakflg;
+ keycode_t *code = 0;
+ char *str;
+
+ breakflg = (scan & FLG_BREAKBIT);
+ scan &= ~FLG_BREAKBIT;
+ code = &scantable[scan];
+
+ if (code->kc_type & (FLG_SHIFT|FLG_CTRL|FLG_ALT)) {
+ if (breakflg) ks->ks_shiftflags &= ~code->kc_type;
+ else ks->ks_shiftflags |= code->kc_type;
+ }
+ if (code->kc_type & (FLG_CAPS|FLG_SCROLL|FLG_NUM)) {
+ if (!breakflg) ks->ks_shiftflags ^= code->kc_type;
+ if (ks->ks_setleds) {
+ (*(ks->ks_setleds))(ks,ks->ks_shiftflags & (FLG_CAPS|FLG_SCROLL|FLG_NUM));
+ }
+ }
+ if (code->kc_type & (FLG_ASCII | FLG_FKEY | FLG_NKPD)) {
+ if (ks->ks_shiftflags & (FLG_SHIFT|FLG_CAPS)) str = code->kc_shifted;
+ else if (ks->ks_shiftflags & FLG_CTRL) str = code->kc_ctrl;
+ else str = code->kc_normal;
+ if (!breakflg) {
+ while (*str) {
+ kbd_enqueuechar(ks,*str++);
+ }
+ }
+ }
+}
+
+
+/* *********************************************************************
+ * KBD_INIT(ks,setleds,ref)
+ *
+ * Initialize a keyboard state object.
+ *
+ * Input parameters:
+ * ks - keyboard state
+ * setleds - routine to call when we want to set the state
+ * of the keyboard's LEDs
+ * ref - data to store in the keyboard state object
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void kbd_init(keystate_t *ks,int (*setleds)(keystate_t *,int),void *ref)
+{
+ memset(ks,0,sizeof(keystate_t));
+ ks->ks_setleds = setleds;
+ ks->ks_ref = ref;
+}
diff --git a/cfe/cfe/pccons/kbd_subr.h b/cfe/cfe/pccons/kbd_subr.h
new file mode 100644
index 0000000..f18f8db
--- /dev/null
+++ b/cfe/cfe/pccons/kbd_subr.h
@@ -0,0 +1,82 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * PC-style keyboard interface File: KBD_SUBR.C
+ *
+ * This module converts a stream of scancodes into ASCII
+ * characters. The scan codes come from a PC-style
+ * keyboard.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define KEYQUEUELEN 16
+
+#define KBDCMD_RESET 0xFF
+#define KBDCMD_SETLEDS 0xED
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef struct keystate_s {
+ int ks_shiftflags;
+ char ks_queue[KEYQUEUELEN];
+ int ks_head;
+ int ks_tail;
+ int (*ks_setleds)(struct keystate_s *ks,int leds);
+ void *ks_ref;
+} keystate_t;
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+int kbd_read(keystate_t *ks);
+int kbd_inpstat(keystate_t *ks);
+void kbd_init(keystate_t *ks,int (*setleds)(keystate_t *,int),void *ref);
+void kbd_doscan(keystate_t *ks,uint8_t scan);
+#define kbd_getref(x) ((x)->ks_ref)
+
+
diff --git a/cfe/cfe/pccons/pcibios.h b/cfe/cfe/pccons/pcibios.h
new file mode 100644
index 0000000..8da8648
--- /dev/null
+++ b/cfe/cfe/pccons/pcibios.h
@@ -0,0 +1,72 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * PCI BIOS constants File: PCIBIOS.H
+ *
+ * This module contains constants related to the X86's PCI
+ * BIOS, as described in the PCI BIOS specification.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#define PCIBIOS_FN_MAJOR 0xB1
+#define PCIBIOS_FN_INSTCHK 0x01
+#define PCIBIOS_FN_FINDDEV 0x02
+#define PCIBIOS_FN_FINDCLASS 0x03
+#define PCIBIOS_FN_RDCFGBYTE 0x08
+#define PCIBIOS_FN_RDCFGWORD 0x09
+#define PCIBIOS_FN_RDCFGDWORD 0x0A
+
+#define PCIBIOS_FN_WRCFGBYTE 0x0B
+#define PCIBIOS_FN_WRCFGWORD 0x0C
+#define PCIBIOS_FN_WRCFGDWORD 0x0D
+#define PCIBIOS_SUCCESSFUL 0
+#define PCIBIOS_DEVICE_NOT_FOUND 0x86
+
+#define PCIBIOS_VERSION 0x0210
+#define PCIBIOS_SIGNATURE 0x20494350
+
+#define PCIBIOS_ROMSIG_OFFSET 0
+#define PCIBIOS_ROMSIG1 0x55
+#define PCIBIOS_ROMSIG2 0xAA
+#define PCIBIOS_ROMSIZE(x) ((unsigned int)(x)*512)
+
+#define PCIBIOS_ROMSIZE_OFFSET 2
+#define PCIBIOS_ROMENTRY_OFFSET 3
diff --git a/cfe/cfe/pccons/vga.h b/cfe/cfe/pccons/vga.h
new file mode 100644
index 0000000..5c43664
--- /dev/null
+++ b/cfe/cfe/pccons/vga.h
@@ -0,0 +1,76 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * VGA definitions File: VGA.H
+ *
+ * This module contains names of the registers and bits
+ * commonly used on VGA adapters.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+#define VGA_GFXCTL_INDEX 0x3CE
+#define VGA_GFXCTL_DATA 0x3CF
+#define VGA_CRTC_INDEX 0x3D4
+#define VGA_CRTC_DATA 0x3D5
+#define VGA_SEQ_INDEX 0x3C4
+#define VGA_SEQ_DATA 0x3C5
+#define VGA_INPSTATUS_R 0x3C2
+#define VGA_MISCOUTPUT_W 0x3C2
+#define VGA_MISCOUTPUT_R 0x3CC
+#define VGA_ATTRIB_INDEX 0x3C0
+#define VGA_ATTRIB_DATA 0x3C1
+#define VGA_FEATURES_W 0x3DA
+#define VGA_EXT_INDEX 0x3D6
+#define VGA_EXT_DATA 0x3D7
+
+#define CRTC_CURSOR_HIGH 0x0E
+#define CRTC_CURSOR_LOW 0x0F
+
+#define VGA_TEXTBUF_COLOR 0xB8000
+#define VGA_TEXTBUF_MONO 0xB0000
+#define VGA_TEXTBUF_SIZE 0x8000
+
+#define VGA_ATTRIB_MONO 7
+
+#define VGA_TEXTMODE_COLS 80
+#define VGA_TEXTMODE_ROWS 25
+
diff --git a/cfe/cfe/pccons/vga_subr.c b/cfe/cfe/pccons/vga_subr.c
new file mode 100644
index 0000000..7704054
--- /dev/null
+++ b/cfe/cfe/pccons/vga_subr.c
@@ -0,0 +1,285 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * VGA "teletype" routines File: VGA_SUBR.C
+ *
+ * These routines implement a simple "glass tty" interface
+ * to a vga monitor.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+#include "lib_malloc.h"
+
+#include "lib_physio.h"
+
+#include "vga_subr.h"
+#include "vga.h"
+
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define OUTB(vga,port,val) (*((vga)->vga_outb))(port,val)
+
+#ifdef __MIPSEB
+#define VGA_SPACE_CHAR 0x2007 /* belongs somewhere else */
+#else
+#define VGA_SPACE_CHAR 0x0720
+#endif
+
+/* *********************************************************************
+ * Data
+ ********************************************************************* */
+
+
+/* *********************************************************************
+ * VGA_CLEAR(vga)
+ *
+ * Clear the VGA screen
+ *
+ * Input parameters:
+ * vga - VGA object
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void vga_clear(vga_term_t *vga)
+{
+ int idx;
+
+ /* Clear the frame buffer */
+
+ for (idx = 0; idx < VGA_TEXTBUF_SIZE; idx+=2) {
+ phys_write16(vga->vga_buffer+idx,VGA_SPACE_CHAR);
+ }
+}
+
+
+/* *********************************************************************
+ * VGA_SETCURSOR(vga,x,y)
+ *
+ * Set the hardware cursor position
+ *
+ * Input parameters:
+ * vga - VGA object
+ * x,y - cursor location
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void vga_setcursor(vga_term_t *vga,int x,int y)
+{
+ unsigned int loc = y*vga->vga_ncols + x;
+
+ OUTB(vga,VGA_CRTC_INDEX,CRTC_CURSOR_HIGH);
+ OUTB(vga,VGA_CRTC_DATA,(loc >> 8) & 0xFF);
+ OUTB(vga,VGA_CRTC_INDEX,CRTC_CURSOR_LOW);
+ OUTB(vga,VGA_CRTC_DATA,(loc >> 0) & 0xFF);
+
+ vga->vga_cursorX = x;
+ vga->vga_cursorY = y;
+}
+
+/* *********************************************************************
+ * VGA_SCROLL(vga)
+ *
+ * Scroll the display up one line
+ *
+ * Input parameters:
+ * vga - VGA object
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void vga_scroll(vga_term_t *vga)
+{
+ int idx;
+ int count;
+ int rowsize;
+ uint32_t t;
+
+ rowsize = vga->vga_ncols * 2;
+ count = (vga->vga_nrows-1) * rowsize;
+
+ for (idx = 0; idx < count; idx+=4) {
+ t = phys_read32(vga->vga_buffer+idx+rowsize);
+ phys_write32(vga->vga_buffer+idx,t);
+ }
+
+ for (idx = 0; idx < rowsize; idx += 2) {
+ phys_write16(vga->vga_buffer+(vga->vga_nrows-1)*rowsize+idx,VGA_SPACE_CHAR);
+ }
+
+ vga_setcursor(vga,0,vga->vga_nrows-1);
+}
+
+/* *********************************************************************
+ * VGA_WRITECHAR(vga,ch,attr)
+ *
+ * Write a character to the display. This routine also
+ * interprets some rudimentary control characters, such
+ * as tab, backspace, linefeed, and carriage return.
+ *
+ * Input parameters:
+ * vga - VGA object
+ * ch - character to write
+ * attr - attribute byte for new character
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void vga_writechar(vga_term_t *vga,uint8_t ch,uint8_t attr)
+{
+ physaddr_t addr;
+
+ switch (ch) {
+ case 0x07:
+ break;
+ case 0x09:
+ vga_writechar(vga,' ',attr);
+ while (vga->vga_cursorX % 8) vga_writechar(vga,' ',attr);
+ break;
+ case 0x0A:
+ vga->vga_cursorY++;
+ if (vga->vga_cursorY > (vga->vga_nrows-1)) {
+ vga_scroll(vga);
+ }
+ break;
+ case 0x08:
+ if (vga->vga_cursorX) {
+ vga->vga_cursorX--;
+ addr = vga->vga_buffer + (vga->vga_cursorX*2+vga->vga_cursorY*vga->vga_ncols*2);
+ phys_write8(addr,' ');
+ }
+ break;
+ case 0x0D:
+ vga->vga_cursorX = 0;
+ break;
+ default:
+ addr = vga->vga_buffer + (vga->vga_cursorX*2+vga->vga_cursorY*vga->vga_ncols*2);
+ phys_write8(addr,ch);
+ phys_write8(addr+1,attr);
+ vga->vga_cursorX++;
+ if (vga->vga_cursorX > (vga->vga_ncols-1)) {
+ vga->vga_cursorX = 0;
+ vga->vga_cursorY++;
+ if (vga->vga_cursorY > (vga->vga_nrows-1)) {
+ vga_scroll(vga);
+ }
+ }
+ break;
+ }
+
+ vga_setcursor(vga,vga->vga_cursorX,vga->vga_cursorY);
+}
+
+/* *********************************************************************
+ * VGA_WRITESTR(vga,str,attr,len)
+ *
+ * Write a string of characters to the VGA
+ *
+ * Input parameters:
+ * vga - VGA object
+ * str - pointer to buffer
+ * attr - attribute byte for characters we're writing
+ * len - number of characters to write
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void vga_writestr(vga_term_t *vga,uint8_t *str,uint8_t attr,int len)
+{
+ while (len) {
+ vga_writechar(vga,*str,attr);
+ str++;
+ len--;
+ }
+}
+
+/* *********************************************************************
+ * VGA_RESET(vga)
+ *
+ * (mostly unused) - reset the VGA
+ *
+ * Input parameters:
+ * vga - vga object
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void vga_reset(vga_term_t *vga)
+{
+ vga_clear(vga);
+}
+
+/* *********************************************************************
+ * VGA_INIT(vga,buffer,outfunc)
+ *
+ * Initialize a VGA object
+ *
+ * Input parameters:
+ * vga - VGA object
+ * buffer - pointer to VGA-style frame buffer (physical addr)
+ * outfunc - pointer to function to write ISA I/O ports
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void vga_init(vga_term_t *vga,physaddr_t buffer,void (*outfunc)(unsigned int port,uint8_t val))
+{
+ vga->vga_buffer = buffer;
+ vga->vga_cursorX = 0;
+ vga->vga_cursorY = 0;
+ vga->vga_nrows = VGA_TEXTMODE_ROWS;
+ vga->vga_ncols = VGA_TEXTMODE_COLS;
+ vga->vga_outb = outfunc;
+}
diff --git a/cfe/cfe/pccons/vga_subr.h b/cfe/cfe/pccons/vga_subr.h
new file mode 100644
index 0000000..eb0e0e0
--- /dev/null
+++ b/cfe/cfe/pccons/vga_subr.h
@@ -0,0 +1,82 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * VGA "teletype" routines File: VGA_SUBR.H
+ *
+ * These routines implement a simple "glass tty" interface
+ * to a vga monitor.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef struct vga_term_s {
+ physaddr_t vga_buffer;
+ int vga_nrows;
+ int vga_ncols;
+ int vga_cursorX;
+ int vga_cursorY;
+ void (*vga_outb)(unsigned int isaport,uint8_t val);
+} vga_term_t;
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+
+void vga_clear(vga_term_t *vga);
+void vga_setcursor(vga_term_t *vga,int x,int y);
+void vga_writechar(vga_term_t *vga,uint8_t ch,uint8_t attr);
+void vga_writestr(vga_term_t *vga,uint8_t *str,uint8_t attr,int len);
+void vga_reset(vga_term_t *vga);
+void vga_init(vga_term_t *vga,physaddr_t buffer,void (*outfunc)(unsigned int port,uint8_t val));
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cfe/cfe/pccons/vgainit.c b/cfe/cfe/pccons/vgainit.c
new file mode 100644
index 0000000..7c22af2
--- /dev/null
+++ b/cfe/cfe/pccons/vgainit.c
@@ -0,0 +1,1164 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * VGA BIOS initialization File: VGAINIT.C
+ *
+ * This module interfaces with the X86 emulator borrowed from
+ * XFree86 to do VGA initialization.
+ *
+ * WARNING: This code is SB1250-specific for now. It's not
+ * hard to change, but then again, aren't we interested in the 1250?
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "sbmips.h"
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+#include "lib_malloc.h"
+#include "pcireg.h"
+#include "pcivar.h"
+#include "cfe_console.h"
+#include "vga.h"
+#include "pcibios.h"
+#include "lib_physio.h"
+#include "vga_subr.h"
+#include "x86mem.h"
+#include "x86emu.h"
+#include "env_subr.h"
+
+
+/* *********************************************************************
+ * Configuration
+ ********************************************************************* */
+
+#define BYTESONLY 0 /* Always write registers as bytes */
+#define VGAINIT_NOISY 0 /* lots of debug output */
+
+/* *********************************************************************
+ * ISA port macros - currently SB1250-specific
+ ********************************************************************* */
+
+#define INB(x) inb(x)
+#define INW(x) inw(x)
+#define INL(x) inl(x)
+#define OUTB(x,y) outb(x,y)
+#define OUTW(x,y) outw(x,y)
+#define OUTL(x,y) outl(x,y)
+
+/* *********************************************************************
+ * ISA memory macros - currently SB1250-specific
+ ********************************************************************* */
+
+typedef uintptr_t vm_offset_t;
+
+#if defined(_P5064_) || defined(_P6064_)
+ #define PCI_MEM_SPACE 0x10000000 /* 128MB: s/w configurable */
+ #define __ISAaddr(addr) ((physaddr_t)(PCI_MEM_SPACE+(addr)))
+#else
+ #define __ISAaddr(addr) ((physaddr_t)0x40000000+(addr))
+#endif
+
+#define __ISAreadbyte(addr) phys_read8(__ISAaddr(addr))
+#define __ISAreadword(addr) phys_read16(__ISAaddr(addr))
+#define __ISAreaddword(addr) phys_read32(__ISAaddr(addr))
+#define __ISAwritebyte(addr,data) phys_write8(__ISAaddr(addr),(data))
+#define __ISAwriteword(addr,data) phys_write16(__ISAaddr(addr),(data))
+#define __ISAwritedword(addr,data) phys_write32(__ISAaddr(addr),(data))
+
+/* *********************************************************************
+ * Other macros
+ ********************************************************************* */
+
+#define OFFSET(addr) (((addr) >> 0) & 0xffff)
+#define SEGMENT(addr) (((addr) >> 4) & 0xf000)
+
+#define BSWAP_SHORT(s) ((((s) >> 8) & 0xFF) | (((s)&0xFF) << 8))
+#define BSWAP_LONG(s) ((((s) & 0xFF000000) >> 24) | \
+ (((s) & 0x00FF0000) >> 8) | \
+ (((s) & 0x0000FF00) << 8) | \
+ (((s) & 0x000000FF) << 24))
+
+
+#ifdef __MIPSEB
+#define CPU_TO_LE16(s) BSWAP_SHORT(s)
+#define CPU_TO_LE32(s) BSWAP_LONG(s)
+#define LE16_TO_CPU(s) BSWAP_SHORT(s)
+#define LE32_TO_CPU(s) BSWAP_LONG(s)
+#else
+#define CPU_TO_LE16(s) (s)
+#define CPU_TO_LE32(s) (s)
+#define LE16_TO_CPU(s) (s)
+#define LE32_TO_CPU(s) (s)
+#endif
+
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+int vga_biosinit(void);
+int vga_probe(void);
+extern void ui_restart(int);
+void vgaraw_dump(char *tail);
+int x86emutest(void);
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+static vga_term_t vga;
+static x86mem_t x86mem;
+
+#define BIOSRAMLOC (0xC0000)
+#define STACKSIZE 4096
+#define IRETOFFSET 12
+static uint8_t x86initcode[] = {
+#if (VGA_TEXTMODE_ROWS == 60)
+ 0xB8,0x02,0x4F, /* mov ax,042F */
+ 0xBB,0x08,0x01, /* mov bx,0108 */ /* VESA 80x60 */
+#else
+ 0xB8,0x03,0x00, /* mov AX,0003 */ /* 80x25 mode */
+#endif
+
+ 0xCD,0x10, /* int 10 */
+ 0xB8,0x34,0x12, /* mov ax,1234 */
+ 0xBB,0x78,0x56, /* mov bx,5678 */
+ 0xCC, /* int 3 */
+ 0xCF}; /* IRET */
+
+static uint8_t x86testcode[] = {
+ 0x90,0x90,0x90,0x90,0x90, /* nop, nop, nop, nop, nop */
+ 0xeb,0x09, /* jmp 10 */
+ 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, /* 9 nops */
+ 0xb8,0x34,0x12, /* mov ax,1234 */
+ 0xbb,0x78,0x56, /* mov bx,5678 */
+ 0xcc, /* int 3 */
+ 0xcf}; /* iret */
+
+static uint32_t __ISAreadmem(x86mem_t *mem,uint32_t addr,int size)
+{
+ unsigned long val;
+
+ switch (size) {
+ case M_BYTE:
+ val = __ISAreadbyte(addr);
+ break;
+ case M_WORD:
+ if (BYTESONLY || (addr & 0x1)) {
+ val = (__ISAreadbyte(addr) | (__ISAreadbyte(addr + 1) << 8));
+ }
+ else {
+ val = __ISAreadword(addr);
+ val = LE16_TO_CPU(val);
+ }
+ break;
+ case M_DWORD:
+ if (BYTESONLY || (addr & 0x3)) {
+ val = (__ISAreadbyte(addr) |
+ (__ISAreadbyte(addr + 1) << 8) |
+ (__ISAreadbyte(addr + 2) << 16) |
+ (__ISAreadbyte(addr + 3) << 24));
+ }
+ else {
+ val = __ISAreaddword(addr);
+ val = LE32_TO_CPU(val);
+ }
+ break;
+ default:
+ val = 0;
+ }
+
+ return val;
+}
+
+
+
+static void __ISAwritemem(x86mem_t *mem,uint32_t addr,uint32_t data,int size)
+{
+ switch (size) {
+ case M_BYTE:
+ __ISAwritebyte(addr, data);
+ break;
+
+ case M_WORD:
+ if (BYTESONLY || (addr & 0x1)) {
+ __ISAwritebyte(addr, data >> 0);
+ __ISAwritebyte(addr + 1, data >> 8);
+ }
+ else {
+ data = CPU_TO_LE16(data);
+ __ISAwriteword(addr, data);
+ }
+ break;
+
+ case M_DWORD:
+ if (BYTESONLY || (addr & 0x3)) {
+ __ISAwritebyte(addr, data >> 0);
+ __ISAwritebyte(addr + 1, data >> 8);
+ __ISAwritebyte(addr + 2, data >> 16);
+ __ISAwritebyte(addr + 3, data >> 24);
+ }
+ else {
+ data = CPU_TO_LE32(data);
+ __ISAwritedword(addr, data);
+ }
+ break;
+ }
+}
+
+
+static u8 __x86emu_rdb(u32 addr)
+{
+#if VGAINIT_NOISY
+ if ((addr < 0x400) || (addr > 0x100000)) {
+ xprintf("Read %08X (int %02X) ",addr,addr/4);
+ printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP);
+ }
+#endif
+ return x86mem_readb(&x86mem,addr);
+}
+
+
+static u16 __x86emu_rdw(u32 addr)
+{
+#if VGAINIT_NOISY
+ if ((addr < 0x400) || (addr > 0x100000)) {
+ xprintf("Read %08X (int %02X) ",addr,addr/4);
+ printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP);
+ }
+#endif
+ return x86mem_readw(&x86mem,addr);
+}
+
+
+static u32 __x86emu_rdl(u32 addr)
+{
+#if VGAINIT_NOISY
+ if ((addr < 0x400) || (addr > 0x100000)) {
+ xprintf("Read %08X (int %02X) ",addr,addr/4);
+ printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP);
+ }
+#endif
+ return x86mem_readl(&x86mem,addr);
+}
+
+
+static void __x86emu_wrb(u32 addr, u8 val)
+{
+#if VGAINIT_NOISY
+ if ((addr < 0x400) || (addr > 0x100000)) {
+ xprintf("Write %08X (int %02X) ",addr,addr/4);
+ printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP);
+ }
+#endif
+ x86mem_writeb(&x86mem,addr,val);
+}
+
+
+static void __x86emu_wrw(u32 addr, u16 val)
+{
+#if VGAINIT_NOISY
+ if ((addr < 0x400) || (addr > 0x100000)) {
+ xprintf("Write %08X %04X (int %02X) ",addr,val,addr/4);
+ printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP);
+ }
+#endif
+ x86mem_writew(&x86mem,addr,val);
+}
+
+
+static void __x86emu_wrl(u32 addr, u32 val)
+{
+#if VGAINIT_NOISY
+ if ((addr < 0x400) || (addr > 0x100000)) {
+ xprintf("Write %08X (int %02X) ",addr,addr/4);
+ printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP);
+ }
+#endif
+ x86mem_writel(&x86mem,addr,val);
+}
+
+
+#define TS_COMMAND 0
+#define TS_DATA1 1
+#define TS_DATA2 2
+static uint16_t timerCount = 0;
+static int timerState = TS_COMMAND;
+static u8 __x86emu_inb(X86EMU_pioAddr port)
+{
+ u8 val;
+
+ /*
+ * Emulate just enough functionality of the
+ * timer chip to fool the Trident BIOS
+ */
+ if (port == 0x40) {
+ timerCount++;
+ switch (timerState) {
+ case TS_COMMAND:
+ return 0;
+ case TS_DATA1:
+ timerState = TS_DATA1;
+ return timerCount & 0xFF;
+ case TS_DATA2:
+ timerState = TS_COMMAND;
+ return (timerCount >> 8) & 0xFF;
+ }
+ }
+
+ val = INB(port);
+
+#if VGAINIT_NOISY
+ /*if (port < 0x100)*/ xprintf("INB %08X %02X\n",port,val);
+ if (console_status()) ui_restart(0);
+#endif
+
+
+ return val;
+}
+
+
+static u16 __x86emu_inw(X86EMU_pioAddr port)
+{
+ u16 val;
+
+ val = INW(port);
+
+ val = LE16_TO_CPU(val);
+
+#if VGAINIT_NOISY
+ /*if (port < 0x100)*/ xprintf("INW %08X %04X\n",port,val);
+#endif
+
+ return val;
+}
+
+
+static u32 __x86emu_inl(X86EMU_pioAddr port)
+{
+ u32 val;
+
+ val = INL(port);
+
+ val = LE32_TO_CPU(val);
+
+#if VGAINIT_NOISY
+ /*if (port < 0x100)*/ xprintf("INL %08X %08X\n",port,val);
+#endif
+
+
+ return val;
+}
+
+
+static void __x86emu_outb(X86EMU_pioAddr port, u8 val)
+{
+ /*
+ * Emulate just enough functionality of the timer
+ * chip to fool the Trident BIOS
+ */
+ if (port == 0x43) {
+ timerCount++;
+ timerState = TS_DATA1;
+ return;
+ }
+
+#if VGAINIT_NOISY
+ /*if (port < 0x100)*/ xprintf("OUTB %08X %08X\n",port,val);
+#endif
+
+ OUTB(port,val);
+}
+
+
+static void __x86emu_outw(X86EMU_pioAddr port, u16 val)
+{
+ val = CPU_TO_LE16(val);
+
+#if VGAINIT_NOISY
+ /*if (port < 0x100)*/ xprintf("OUTW %08X %04X ",port,val);
+ printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP);
+#endif
+
+ OUTW(port,val);
+}
+
+
+static void __x86emu_outl(X86EMU_pioAddr port, u32 val)
+{
+ if (port == 0x2D) return;
+
+ val = CPU_TO_LE32(val);
+
+#if VGAINIT_NOISY
+ /*if (port < 0x100)*/ xprintf("OUTL %08X %08X ",port,val);
+ printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP);
+#endif
+
+
+ OUTL(port,val);
+}
+
+
+static void regs2tag(pcitag_t *tag)
+{
+ pcitag_t mytag;
+ int bus,device,function;
+
+ bus = M.x86.R_BH;
+ device = M.x86.R_BL >> 3;
+ function = M.x86.R_BL & 0x07;
+
+ mytag = pci_make_tag(bus,device,function);
+
+ *tag = mytag;
+}
+
+static void __SIMint10(int intno)
+{
+#if VGAINIT_NOISY
+ xprintf("Int10: BIOS function AX=%04X\n",M.x86.R_AX);
+#endif
+
+ /*
+ * The only BIOS function that VGAs appear to
+ * depend on in the real BIOS is the one
+ * that enables/disables video memory.
+ */
+
+ if ((M.x86.R_AH == 0x12) && (M.x86.R_BL == 0x32)) {
+ if (M.x86.R_AL == 0) {
+ /* enable video memory */
+ __x86emu_outb(VGA_MISCOUTPUT_W, __x86emu_inb(VGA_MISCOUTPUT_R) | 0x02);
+ return;
+ }
+ else if (M.x86.R_AL == 1) {
+ /* disable video memory */
+ __x86emu_outb(VGA_MISCOUTPUT_W, __x86emu_inb(VGA_MISCOUTPUT_R) & ~0x02);
+ return;
+ }
+ else {
+ xprintf("Int10 unknown function AX=%04X\n",
+ M.x86.R_AX);
+ }
+ }
+ else {
+
+ /* Otherwise, pass the int10 on to the ROM */
+
+ X86EMU_prepareForInt(0x10);
+ }
+}
+
+
+static void __SIMint3(int intno)
+{
+#if VGAINIT_NOISY
+ xprintf("Int3: Breakpoint reached.\n");
+#endif
+ HALT_SYS();
+}
+
+
+static void __SIMintunk(int intno)
+{
+#if VGAINIT_NOISY
+ xprintf("Int%02X: Unhandled interrupt!\n",intno);
+#endif
+ HALT_SYS();
+}
+
+static void __SIMint42(int intno)
+{
+#if VGAINIT_NOISY
+ xprintf("Int42: Function AX=%04X\n",M.x86.R_AX);
+#endif
+ switch (M.x86.R_AH) {
+ case 0:
+ vga_reset(&vga);
+ break;
+ default:
+#if VGAINIT_NOISY
+ xprintf("Int42: Unknown INT42 command: %x\n",M.x86.R_AH);
+#endif
+ break;
+ }
+}
+
+
+static void __SIMint6D(int intno)
+{
+ int reflect = 1;
+
+#if VGAINIT_NOISY
+ xprintf("Int6D: Function AX=%04X\n",M.x86.R_AX);
+#endif
+
+ switch (M.x86.R_AH) {
+ case 0:
+ break;
+ case 0x13:
+ if (M.x86.R_AL == 1) {
+ unsigned long addr;
+ unsigned long count;
+ uint8_t ch;
+
+ addr = (M.x86.R_ES << 4) + M.x86.R_BP;
+ count = M.x86.R_CX;
+
+ while (count) {
+ ch = __x86emu_rdb(addr);
+ vga_writechar(&vga,ch,M.x86.R_BL);
+ addr++;
+ count--;
+ }
+ reflect = 0;
+ }
+ break;
+ default:
+#if VGAINIT_NOISY
+ xprintf("Unknown INT6D command: %x\n",M.x86.R_AH);
+#endif
+ break;
+ }
+
+ if (reflect) X86EMU_prepareForInt(0x6D);
+}
+
+
+
+static void __SIMint1A(int intno)
+{
+ pcitag_t tag;
+ int bus,device,function;
+ int ret;
+
+ if (M.x86.R_AH != PCIBIOS_FN_MAJOR) return;
+
+ switch (M.x86.R_AL) {
+ case PCIBIOS_FN_INSTCHK:
+ M.x86.R_EAX = 0x00;
+ M.x86.R_AL = 0x01;
+ M.x86.R_EDX = PCIBIOS_SIGNATURE;
+ M.x86.R_EBX = PCIBIOS_VERSION;
+ M.x86.R_ECX &= 0xFF00;
+ M.x86.R_CL = 0; /* Highest bus number */
+#ifdef VGAINIT_NOISY
+ xprintf("Int1A: Installation check\n");
+#endif
+ CLEAR_FLAG(F_CF);
+ break;
+
+ case PCIBIOS_FN_FINDDEV:
+ ret = pci_find_device(M.x86.R_DX,M.x86.R_CX,M.x86.R_SI,&tag);
+#if VGAINIT_NOISY
+ xprintf("Int1A: Find device VID=%04X,DID=%04X,Idx=%d: ",
+ M.x86.R_DX,M.x86.R_CX,M.x86.R_SI);
+ if (ret == 0) {
+ pci_break_tag(tag,&bus,&device,&function);
+ xprintf("Found Bus%d, Dev%d, Func%d\n",bus,device,function);
+ }
+ else {
+ xprintf("not found.\n");
+ }
+#endif
+ if (ret == 0) {
+ pci_break_tag(tag,&bus,&device,&function);
+ M.x86.R_BH = bus;
+ M.x86.R_BL = (device << 3) | function;
+ M.x86.R_AH = PCIBIOS_SUCCESSFUL;
+ }
+ else {
+ M.x86.R_AH = PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ CONDITIONAL_SET_FLAG((M.x86.R_AH != PCIBIOS_SUCCESSFUL),F_CF);
+ break;
+
+ case PCIBIOS_FN_FINDCLASS:
+ ret = pci_find_class(M.x86.R_ECX,M.x86.R_SI,&tag);
+#if VGAINIT_NOISY
+ xprintf("Int1A: Find Class %08X,Idx=%d: ",
+ M.x86.R_ECX,M.x86.R_SI);
+ if (ret == 0) {
+ pci_break_tag(tag,&bus,&device,&function);
+ xprintf("Found Bus%d, Dev%d, Func%d\n",bus,device,function);
+ }
+ else {
+ xprintf("not found.\n");
+ }
+#endif
+
+ if (ret == 0) {
+ pci_break_tag(tag,&bus,&device,&function);
+ M.x86.R_BH = bus;
+ M.x86.R_BL = (device << 3) | function;
+ M.x86.R_AH = PCIBIOS_SUCCESSFUL;
+ }
+ else {
+ M.x86.R_AH =PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ CONDITIONAL_SET_FLAG((M.x86.R_AH != PCIBIOS_SUCCESSFUL),F_CF);
+ break;
+
+ case PCIBIOS_FN_RDCFGBYTE:
+ regs2tag(&tag);
+ M.x86.R_CL = pci_conf_read8(tag,M.x86.R_DI);
+ M.x86.R_AH = PCIBIOS_SUCCESSFUL;
+#if VGAINIT_NOISY
+ xprintf("Int1A: Read Cfg Byte %04X from ",M.x86.R_DI);
+ pci_break_tag(tag,&bus,&device,&function);
+ xprintf("Bus%d, Dev%d, Func%d",bus,device,function);
+ xprintf(": %02X\n",M.x86.R_CX);
+#endif
+
+ CLEAR_FLAG(F_CF);
+ break;
+
+ case PCIBIOS_FN_RDCFGWORD:
+ regs2tag(&tag);
+ M.x86.R_CX = pci_conf_read16(tag,M.x86.R_DI);
+ M.x86.R_AH = PCIBIOS_SUCCESSFUL;
+#if VGAINIT_NOISY
+ xprintf("Int1A: Read Cfg Word %04X from ",M.x86.R_DI);
+ pci_break_tag(tag,&bus,&device,&function);
+ xprintf("Bus%d, Dev%d, Func%d",bus,device,function);
+ xprintf(": %04X\n",M.x86.R_CX);
+#endif
+ CLEAR_FLAG(F_CF);
+ break;
+
+ case PCIBIOS_FN_RDCFGDWORD:
+ regs2tag(&tag);
+ M.x86.R_ECX = pci_conf_read(tag,M.x86.R_DI);
+#if VGAINIT_NOISY
+ xprintf("Int1A: Read Cfg Dword %04X from ",M.x86.R_DI);
+ pci_break_tag(tag,&bus,&device,&function);
+ xprintf("Bus%d, Dev%d, Func%d",bus,device,function);
+ xprintf(": %08X\n",M.x86.R_ECX);
+#endif
+ M.x86.R_AH = PCIBIOS_SUCCESSFUL;
+ CLEAR_FLAG(F_CF);
+ break;
+
+ case PCIBIOS_FN_WRCFGBYTE:
+ regs2tag(&tag);
+ pci_conf_write8(tag,M.x86.R_DI,M.x86.R_CL);
+#if VGAINIT_NOISY
+ xprintf("Int1A: Write Cfg byte %04X to ",M.x86.R_DI);
+ pci_break_tag(tag,&bus,&device,&function);
+ xprintf("Bus%d, Dev%d, Func%d",bus,device,function);
+ xprintf(": %02X\n",M.x86.R_CL);
+#endif
+
+ M.x86.R_AH = PCIBIOS_SUCCESSFUL;
+ CLEAR_FLAG(F_CF);
+ break;
+
+ case PCIBIOS_FN_WRCFGWORD:
+ regs2tag(&tag);
+ pci_conf_write16(tag,M.x86.R_DI,M.x86.R_CX);
+#if VGAINIT_NOISY
+ xprintf("Int1A: Write Cfg Word %04X to ",M.x86.R_DI);
+ pci_break_tag(tag,&bus,&device,&function);
+ xprintf("Bus%d, Dev%d, Func%d",bus,device,function);
+ xprintf(": %04X\n",M.x86.R_CX);
+#endif
+ M.x86.R_AH = PCIBIOS_SUCCESSFUL;
+ CLEAR_FLAG(F_CF);
+ break;
+
+ case PCIBIOS_FN_WRCFGDWORD:
+ regs2tag(&tag);
+ pci_conf_write(tag,M.x86.R_DI,M.x86.R_ECX);
+#if VGAINIT_NOISY
+ xprintf("Int1A: Write Cfg Dword %04X to ",M.x86.R_DI);
+ pci_break_tag(tag,&bus,&device,&function);
+ xprintf("Bus%d, Dev%d, Func%d",bus,device,function);
+ xprintf(": %08X\n",M.x86.R_ECX);
+#endif
+ M.x86.R_AH = PCIBIOS_SUCCESSFUL;
+ CLEAR_FLAG(F_CF);
+ break;
+
+ default:
+#if VGAINIT_NOISY
+ xprintf("Int1A: Unimplemented PCI BIOS function AX=%04x\n", M.x86.R_AX);
+#endif
+ break;
+ }
+}
+
+
+
+static int x86init(void)
+{
+ /*
+ * Access functions for I/O ports
+ */
+ static X86EMU_pioFuncs piofuncs = {
+ __x86emu_inb,
+ __x86emu_inw,
+ __x86emu_inl,
+ __x86emu_outb,
+ __x86emu_outw,
+ __x86emu_outl
+ };
+
+ /*
+ * Access functions for memory
+ */
+ static X86EMU_memFuncs memfuncs = {
+ __x86emu_rdb,
+ __x86emu_rdw,
+ __x86emu_rdl,
+ __x86emu_wrb,
+ __x86emu_wrw,
+ __x86emu_wrl
+ };
+
+ /*
+ * Interrupt table
+ */
+ void (*funcs[256])(int num); /* XXX: can be 2 kilobytes! */
+ int idx;
+
+ /*
+ * Establish hooks in the simulator
+ */
+ X86EMU_setupMemFuncs(&memfuncs);
+ X86EMU_setupPioFuncs(&piofuncs);
+
+ /*
+ * Decode what X86 software interrupts we need to hook
+ */
+
+ for (idx = 0; idx < 256; idx++) {
+ funcs[idx] = __SIMintunk; /* assume all are bad */
+ }
+ funcs[0x42] = __SIMint42; /* int42: video BIOS */
+ funcs[0x1F] = NULL; /* reflect INT1F */
+ funcs[0x43] = NULL; /* reflect INT43 */
+ funcs[0x6D] = __SIMint6D; /* int6D: video BIOS */
+
+ funcs[0x03] = __SIMint3; /* int3: firmware exit */
+ funcs[0x10] = __SIMint10; /* int10: video BIOS */
+ funcs[0x1A] = __SIMint1A; /* int1A: PCI BIOS */
+
+ X86EMU_setupIntrFuncs(funcs);
+
+ x86mem_init(&x86mem);
+ x86mem_hook(&x86mem,0xA0000,__ISAreadmem,__ISAwritemem);
+ x86mem_hook(&x86mem,0xA8000,__ISAreadmem,__ISAwritemem);
+ x86mem_hook(&x86mem,0xB0000,__ISAreadmem,__ISAwritemem);
+ x86mem_hook(&x86mem,0xB8000,__ISAreadmem,__ISAwritemem);
+
+ return 0;
+
+}
+
+
+static void x86uninit(void)
+{
+ x86mem_uninit(&x86mem);
+}
+
+
+int vga_probe(void)
+{
+ pcitag_t tag;
+
+ if (pci_find_class(PCI_CLASS_DISPLAY,0,&tag) == 0) {
+ return 0;
+ }
+
+ return -1;
+}
+
+int vga_biosinit(void)
+{
+ physaddr_t biosaddr;
+ pcitag_t tag;
+ uint32_t addr;
+ uint32_t romaddr;
+ uint32_t destaddr;
+ uint32_t stackaddr;
+ uint32_t iretaddr;
+ unsigned int biossize;
+ int bus,device,function;
+ int idx;
+ int res;
+
+ if (pci_find_class(PCI_CLASS_DISPLAY,0,&tag) == 0) {
+ romaddr = pci_conf_read(tag,PCI_MAPREG_ROM);
+ pci_conf_write(tag,PCI_MAPREG_ROM,romaddr | PCI_MAPREG_ROM_ENABLE);
+ }
+ else {
+ xprintf("No suitable VGA device found in the system.\n");
+ return -1;
+ }
+
+ addr = romaddr;
+ addr &= PCI_MAPREG_ROM_ADDR_MASK;
+#if defined(_P5064_) || defined(_P6064_)
+ biosaddr = cpu_isamap((vm_offset_t) romaddr,0);
+#else
+ biosaddr = (physaddr_t) romaddr;
+#endif
+
+ /*
+ * Check for the presence of a VGA BIOS on this adapter.
+ */
+
+ if (!((phys_read8(biosaddr+PCIBIOS_ROMSIG_OFFSET+0) == PCIBIOS_ROMSIG1) &&
+ (phys_read8(biosaddr+PCIBIOS_ROMSIG_OFFSET+1) == PCIBIOS_ROMSIG2))) {
+ xprintf("No VGA BIOS on this adapter.\n");
+ pci_conf_write(tag,PCI_MAPREG_ROM,romaddr);
+ return -1;
+ }
+ biossize = PCIBIOS_ROMSIZE(phys_read8(biosaddr+PCIBIOS_ROMSIZE_OFFSET));
+
+#if VGAINIT_NOISY
+ xprintf("VGA BIOS size is %d bytes\n",biossize);
+#endif
+
+ /*
+ * Initialize the X86 emulator
+ */
+
+ if (x86init() != 0) {
+ xprintf("X86 emulator did not initialize.\n");
+ pci_conf_write(tag,PCI_MAPREG_ROM,romaddr);
+ return -1;
+ }
+
+ /*
+ * Allocate space for the ROM BIOS and the stack.
+ * The basic layout is:
+ *
+ * C000:0000 VGA BIOS
+ * C000:XXXX end of VGA BIOS, start of stack
+ * C000:YYYY end of stack, start of init code
+ * C000:ZZZZ end of allocated memory
+ *
+ * We put a little code stub after the stack to allow us to have
+ * a clean exit from the simulator.
+ */
+
+
+ destaddr = BIOSRAMLOC;
+ stackaddr = destaddr + biossize + STACKSIZE;
+
+ /*
+ * Copy the BIOS from the PCI rom into RAM
+ */
+
+#if VGAINIT_NOISY
+ xprintf("Copying VGA BIOS to RAM.\n");
+#endif
+
+ for (idx = 0; idx < biossize; idx+=4) {
+ uint32_t b;
+
+ b = phys_read32(biosaddr+idx);
+ x86mem_memcpy(&x86mem,destaddr+idx,(uint8_t *) &b,sizeof(uint32_t));
+ }
+
+ /*
+ * Gross! The NVidia TNT2 BIOS expects to
+ * find a PC ROM BIOS date (just the slashes)
+ * at the right place in the ROMs.
+ */
+
+ x86mem_memcpy(&x86mem,0xFFFF5,"08/13/99",8);
+
+ /*
+ * Turn off the BIOS ROM, we have our copy now.
+ */
+
+ pci_conf_write(tag,PCI_MAPREG_ROM,romaddr);
+
+ /*
+ * Point certain vectors at a dummy IRET in our code space.
+ * Some ROMs don't take too kindly to null vectors, like
+ * the 3dfx Voodoo3 BIOS, which makes sure int1a is
+ * filled in before it attempts to call it. The
+ * code here is never really executed, since the emulator
+ * hooks it.
+ */
+
+ iretaddr = stackaddr + IRETOFFSET;
+ __x86emu_wrw(0x1A*4+0,OFFSET(iretaddr));
+ __x86emu_wrw(0x1A*4+2,SEGMENT(iretaddr));
+
+
+ /*
+ * The actual code begins 3 bytes after the beginning of the ROM. Set
+ * the start address to the first byte of executable code.
+ */
+
+ M.x86.R_CS = SEGMENT(destaddr + PCIBIOS_ROMENTRY_OFFSET);
+ M.x86.R_IP = OFFSET(destaddr + PCIBIOS_ROMENTRY_OFFSET);
+
+ /*
+ * Set the stack to point after our copy of the ROM
+ */
+
+ M.x86.R_SS = SEGMENT(stackaddr - 8);
+ M.x86.R_SP = OFFSET(stackaddr - 8);
+
+ /*
+ * GROSS! The Voodoo3 card expects BP to have
+ * the following value:
+ */
+
+ M.x86.R_BP = 0x197;
+
+ /*
+ * The PCI BIOS spec says you pass the bus, device, and function
+ * numbers in the AX register when starting the ROM code.
+ */
+
+ pci_break_tag(tag,&bus,&device,&function);
+ M.x86.R_AH = bus;
+ M.x86.R_AL = (device << 3) | (function & 7);
+
+ /*
+ * Arrange for the return address to point to a little piece
+ * of code that will do an int10 to set text mode, followed
+ * by storing a couple of simple signatures in the registers,
+ * and an int3 to stop the simulator.
+ *
+ * The location of this piece of code is just after our
+ * stack, and since the stack grows down, this is in 'stackaddr'
+ */
+
+ __x86emu_wrw(stackaddr-8,OFFSET(stackaddr));
+ __x86emu_wrw(stackaddr-6,SEGMENT(stackaddr));
+
+ /* copy in the code. */
+
+ for (idx = 0; idx < sizeof(x86initcode); idx++) {
+ __x86emu_wrb(stackaddr+idx,x86initcode[idx]);
+ }
+
+ /*
+ * Set up the VGA console descriptor. We need this to process the
+ * int10's that write firmware copyright notices and such.
+ */
+
+ vga_init(&vga,(__ISAaddr(VGA_TEXTBUF_COLOR)),outb);
+
+ /*
+ * Launch the simulator.
+ */
+
+ xprintf("Initializing VGA.\n");
+#ifdef DEBUG
+ X86EMU_trace_on();
+#endif
+ X86EMU_exec();
+
+ /*
+ * Check for the magic exit values in the registers. These get set
+ * by the code in the array 'x86initcode' that was loaded above
+ */
+
+ if ((M.x86.R_AX == 0x1234) && (M.x86.R_BX == 0x5678)) res = 0;
+ else res = -1;
+
+ /*
+ * Done!
+ */
+
+ x86uninit();
+
+ if (res < 0) {
+ xprintf("VGA initialization failed.\n");
+ }
+ else {
+ char temp[32];
+ char *str = "If you can see this message, the VGA has been successfully initialized!\r\n\r\n";
+
+ xprintf("VGA initialization successful.\n");
+ vga_writestr(&vga,str,0x07,strlen(str));
+
+ sprintf(temp,"%d",VGA_TEXTMODE_ROWS);
+ env_setenv("VGA_ROWS",temp,ENV_FLG_BUILTIN | ENV_FLG_READONLY | ENV_FLG_ADMIN);
+ sprintf(temp,"%d",VGA_TEXTMODE_COLS);
+ env_setenv("VGA_COLS",temp,ENV_FLG_BUILTIN | ENV_FLG_READONLY | ENV_FLG_ADMIN);
+
+ }
+
+ return res;
+}
+
+int x86emutest(void)
+{
+ uint32_t destaddr;
+ uint32_t stackaddr;
+ int res;
+
+ /*
+ * Initialize the X86 emulator
+ */
+
+ if (x86init() != 0) {
+ xprintf("X86 emulator did not initialize.\n");
+ return -1;
+ }
+
+ destaddr = BIOSRAMLOC;
+ stackaddr = destaddr + 1024;
+
+ /*
+ * Copy the BIOS from the PCI rom into RAM
+ */
+
+ xprintf("Copying test program to RAM.\n");
+ x86mem_memcpy(&x86mem,destaddr,x86testcode,sizeof(x86testcode));
+
+ /*
+ * The actual code begins 3 bytes after the beginning of the ROM. Set
+ * the start address to the first byte of executable code.
+ */
+
+ M.x86.R_CS = SEGMENT(destaddr + PCIBIOS_ROMENTRY_OFFSET);
+ M.x86.R_IP = OFFSET(destaddr + PCIBIOS_ROMENTRY_OFFSET);
+
+ /*
+ * Set the stack to point after our copy of the ROM
+ */
+
+ M.x86.R_SS = SEGMENT(stackaddr - 8);
+ M.x86.R_SP = OFFSET(stackaddr - 8);
+
+ /*
+ * Launch the simulator.
+ */
+
+ xprintf("Running X86emu test.\n");
+#ifdef DEBUG
+ X86EMU_trace_on();
+#endif
+ X86EMU_exec();
+
+ /*
+ * Check for the magic exit values in the registers. These get set
+ * by the code in the array 'x86initcode' that was loaded above
+ */
+
+ if ((M.x86.R_AX == 0x1234) && (M.x86.R_BX == 0x5678)) res = 0;
+ else res = -1;
+
+ /*
+ * Done!
+ */
+
+ x86uninit();
+
+ if (res < 0) xprintf("X86emu test failed.\n");
+ else xprintf("X86emu test successful.\n");
+
+ return res;
+}
+
+
+
+void vgaraw_dump(char *tail)
+{
+ physaddr_t biosaddr;
+ pcitag_t tag;
+ uint32_t addr;
+ uint32_t romaddr;
+ unsigned int biossize;
+ int idx;
+ int res;
+
+ if (pci_find_class(PCI_CLASS_DISPLAY,0,&tag) == 0) {
+ romaddr = pci_conf_read(tag,PCI_MAPREG_ROM);
+ pci_conf_write(tag,PCI_MAPREG_ROM,romaddr | PCI_MAPREG_ROM_ENABLE);
+ }
+ else {
+ xprintf("No suitable VGA device found in the system.\n");
+ return ;
+ }
+
+ addr = romaddr;
+ addr &= PCI_MAPREG_ROM_ADDR_MASK;
+
+ /* XXX This won't work if the PCI space is remapped somewhere else. */
+#if defined(_P5064_) || defined(_P6064_)
+ biosaddr = cpu_isamap((vm_offset_t) romaddr,0);
+#else
+ biosaddr = romaddr;
+#endif
+
+ /*
+ * Check for the presence of a VGA BIOS on this adapter.
+ */
+
+ xprintf("VGA BIOS is mapped to %08X\n",(uint32_t) biosaddr);
+
+ if (!((phys_read8(biosaddr+PCIBIOS_ROMSIG_OFFSET+0) == PCIBIOS_ROMSIG1) &&
+ (phys_read8(biosaddr+PCIBIOS_ROMSIG_OFFSET+1) == PCIBIOS_ROMSIG2))) {
+ xprintf("No VGA BIOS on this adapter, assuming 32K ROM\n");
+ biossize = 32768;
+ return;
+ }
+ else {
+ biossize = PCIBIOS_ROMSIZE(phys_read8(biosaddr+PCIBIOS_ROMSIZE_OFFSET));
+ xprintf("VGA BIOS size is %d bytes\n",biossize);
+ }
+
+ for (idx = 0; idx < biossize; idx+=16) {
+ xprintf("%04X: ",idx);
+ for (res = 0; res < 16; res++) {
+ xprintf("%02X ",phys_read8(biosaddr+idx+res));
+ }
+ xprintf("\n");
+ if (console_status()) break;
+ }
+
+// pci_conf_write(tag,PCI_MAPREG_ROM,romaddr);
+
+}
diff --git a/cfe/cfe/pccons/x86mem.c b/cfe/cfe/pccons/x86mem.c
new file mode 100644
index 0000000..2e9c49e
--- /dev/null
+++ b/cfe/cfe/pccons/x86mem.c
@@ -0,0 +1,423 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * X86 simulator sparse memory File: X86MEM.C
+ *
+ * This module implements X86 memory for the X86 emulator
+ * used by the BIOS simulator. To avoid allocating the
+ * entire 1MB of PC's addressable memory, this is a "sparse"
+ * memory model, allocating chunks of storage as needed.
+ * VGA BIOSes seem to do all sorts of bizarre things to memory
+ * so this helps reduce the total amount we need to allocate
+ * significantly.
+ *
+ * In addition, this module lets the simulator "hook"
+ * ranges of memory to be handled by a callback
+ * routine. This is used so that we can redirect
+ * accesses to VGA memory space to the PCI bus handler.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "x86mem.h"
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define BSWAP_SHORT(s) ((((s) >> 8) & 0xFF) | (((s)&0xFF) << 8))
+#define BSWAP_LONG(s) ((((s) & 0xFF000000) >> 24) | \
+ (((s) & 0x00FF0000) >> 8) | \
+ (((s) & 0x0000FF00) << 8) | \
+ (((s) & 0x000000FF) << 24))
+
+
+/* *********************************************************************
+ * X86MEM_INIT()
+ *
+ * Initialize an X86mem object
+ *
+ * Input parameters:
+ * mem - X86mem object
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void x86mem_init(x86mem_t *mem)
+{
+ memset(mem,0,sizeof(mem));
+}
+
+/* *********************************************************************
+ * X86MEM_UNINIT(mem)
+ *
+ * Uninitialize an X86mem object, freeing any storage
+ * associated with it.
+ *
+ * Input parameters:
+ * mem - x86mem object
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void x86mem_uninit(x86mem_t *mem)
+{
+ int idx;
+
+ for (idx = 0; idx < X86MEM_CHUNKS; idx++) {
+ if (mem->data[idx]) {
+ KFREE(mem->data[idx]);
+ mem->data[idx] = NULL;
+ }
+ }
+}
+
+/* *********************************************************************
+ * X86MEM_READB(mem,addr)
+ *
+ * Read a byte of memory from the X86mem object.
+ *
+ * Input parameters:
+ * mem - x86mem object
+ * addr - address of byte to read
+ *
+ * Return value:
+ * byte read
+ ********************************************************************* */
+
+uint8_t x86mem_readb(x86mem_t *mem,uint32_t addr)
+{
+ uint8_t *p;
+
+ if (mem->read[X86MEM_REGION(addr)]) {
+ return (uint8_t) (*(mem->read[X86MEM_REGION(addr)]))(mem,addr,1);
+ }
+
+ p = (mem->data[X86MEM_REGION(addr)]);
+
+ if (p) {
+ return *(p + X86MEM_OFFSET(addr));
+ }
+ else {
+ return 0;
+ }
+}
+
+/* *********************************************************************
+ * X86MEM_READW(mem,addr)
+ *
+ * Read a 16-bit word of memory from the X86mem object.
+ *
+ * Input parameters:
+ * mem - x86mem object
+ * addr - address of word to read
+ *
+ * Return value:
+ * word read
+ ********************************************************************* */
+
+uint16_t x86mem_readw(x86mem_t *mem,uint32_t addr)
+{
+ uint8_t *p;
+ uint16_t ret;
+
+ if (mem->read[X86MEM_REGION(addr)]) {
+ return (uint8_t) (*(mem->read[X86MEM_REGION(addr)]))(mem,addr,2);
+ }
+
+ p = (mem->data[X86MEM_REGION(addr)]);
+ if (!p) return 0;
+
+ if ((addr & 1) || (X86MEM_OFFSET(addr) == X86MEM_CHUNKSIZE-1)) {
+
+ ret = ((uint16_t) x86mem_readb(mem,addr+0)) |
+ (((uint16_t) x86mem_readb(mem,addr+1)) << 8);
+ return ret;
+ }
+ else {
+ ret = *((uint16_t *) (p+X86MEM_OFFSET(addr)));
+#ifdef __MIPSEB
+ ret = BSWAP_SHORT(ret);
+#endif
+ }
+
+ return ret;
+}
+
+/* *********************************************************************
+ * X86MEM_READL(mem,addr)
+ *
+ * Read a 32-bit dword of memory from the X86mem object.
+ *
+ * Input parameters:
+ * mem - x86mem object
+ * addr - address of dword to read
+ *
+ * Return value:
+ * dword read
+ ********************************************************************* */
+
+uint32_t x86mem_readl(x86mem_t *mem,uint32_t addr)
+{
+ uint8_t *p;
+ uint32_t ret;
+
+ if (mem->read[X86MEM_REGION(addr)]) {
+ return (uint8_t) (*(mem->read[X86MEM_REGION(addr)]))(mem,addr,4);
+ }
+
+ p = (mem->data[X86MEM_REGION(addr)]);
+ if (!p) return 0;
+
+ if ((addr & 3) || (X86MEM_OFFSET(addr) >= X86MEM_CHUNKSIZE-3)) {
+ ret = ((uint32_t) x86mem_readb(mem,addr+0)) |
+ (((uint32_t) x86mem_readb(mem,addr+1)) << 8) |
+ (((uint32_t) x86mem_readb(mem,addr+2)) << 16) |
+ (((uint32_t) x86mem_readb(mem,addr+3)) << 24);
+ }
+ else {
+ ret = *((uint32_t *) (p+X86MEM_OFFSET(addr)));
+#ifdef __MIPSEB
+ ret = BSWAP_LONG(ret);
+#endif
+ }
+
+ return ret;
+}
+
+/* *********************************************************************
+ * X86MEM_WRITEB(mem,addr,data)
+ *
+ * Write a byte to the X86mem object
+ *
+ * Input parameters:
+ * mem - x86mem object
+ * addr - address of byte to write
+ * data - data to write
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+void x86mem_writeb(x86mem_t *mem,uint32_t addr,uint8_t data)
+{
+ uint8_t *p;
+
+ if (mem->write[X86MEM_REGION(addr)]) {
+ (*(mem->write[X86MEM_REGION(addr)]))(mem,addr,data,1);
+ return;
+ }
+
+ p = (mem->data[X86MEM_REGION(addr)]);
+
+ if (p) {
+ *(p + X86MEM_OFFSET(addr)) = data;
+ }
+ else {
+ p = mem->data[X86MEM_REGION(addr)] = KMALLOC(X86MEM_CHUNKSIZE,sizeof(uint32_t));
+ if (p) {
+ memset(p,0,X86MEM_CHUNKSIZE);
+ *(p + X86MEM_OFFSET(addr)) = data;
+ }
+ }
+}
+
+/* *********************************************************************
+ * X86MEM_WRITEW(mem,addr,data)
+ *
+ * Write a 16-bit word to the X86mem object
+ *
+ * Input parameters:
+ * mem - x86mem object
+ * addr - address of word to write
+ * data - data to write
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+void x86mem_writew(x86mem_t *mem,uint32_t addr,uint16_t data)
+{
+ uint8_t *p;
+
+ if (mem->write[X86MEM_REGION(addr)]) {
+ (*(mem->write[X86MEM_REGION(addr)]))(mem,addr,data,2);
+ return;
+ }
+
+ p = (mem->data[X86MEM_REGION(addr)]);
+
+ if (!p || (addr & 1) || (X86MEM_OFFSET(addr) == X86MEM_CHUNKSIZE-1)) {
+ x86mem_writeb(mem,addr+0,(data & 0xFF));
+ x86mem_writeb(mem,addr+1,((data >> 8) & 0xFF));
+ }
+ else {
+#ifdef __MIPSEB
+ data = BSWAP_SHORT(data);
+#endif
+ *((uint16_t *) (p+X86MEM_OFFSET(addr))) = data;
+ }
+}
+
+/* *********************************************************************
+ * X86MEM_WRITEL(mem,addr,data)
+ *
+ * Write a 32-bit dword to the X86mem object
+ *
+ * Input parameters:
+ * mem - x86mem object
+ * addr - address of dword to write
+ * data - data to write
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+void x86mem_writel(x86mem_t *mem,uint32_t addr,uint32_t data)
+{
+ uint8_t *p;
+
+ if (mem->write[X86MEM_REGION(addr)]) {
+ (*(mem->write[X86MEM_REGION(addr)]))(mem,addr,data,4);
+ return;
+ }
+
+ p = (mem->data[X86MEM_REGION(addr)]);
+
+ if (!p || (addr & 3) || (X86MEM_OFFSET(addr) >= X86MEM_CHUNKSIZE-3)) {
+ x86mem_writeb(mem,addr+0,(data & 0xFF));
+ x86mem_writeb(mem,addr+1,((data >> 8) & 0xFF));
+ x86mem_writeb(mem,addr+2,((data >> 16) & 0xFF));
+ x86mem_writeb(mem,addr+3,((data >> 24) & 0xFF));
+ }
+ else {
+#ifdef __MIPSEB
+ data = BSWAP_LONG(data);
+#endif
+ *((uint32_t *) (p+X86MEM_OFFSET(addr))) = data;
+ }
+}
+
+/* *********************************************************************
+ * X86MEM_MEMCPY(mem,dest,src,cnt)
+ *
+ * memcpy data into the X86mem object
+ *
+ * Input parameters:
+ * mem - x86mem object
+ * destaddr - destination x86mem address
+ * src - source local address
+ * cnt - number of bytes to copy
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void x86mem_memcpy(x86mem_t *mem,uint32_t destaddr,uint8_t *src,int count)
+{
+ while (count) {
+ x86mem_writeb(mem,destaddr,*src);
+ destaddr++;
+ src++;
+ count--;
+ }
+}
+
+
+/* *********************************************************************
+ * X86MEM_HOOK(mem,addr,readf,writef)
+ *
+ * Establish a hook for a block of simulated memory
+ *
+ * Input parameters:
+ * mem - x86mem object
+ * addr - address in memory, should be aligned on a "chunk"
+ * boundary.
+ * readf - function to call on READ accesses
+ * writef - function to call on WRITE accesses
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void x86mem_hook(x86mem_t *mem,uint32_t chunkaddr,
+ uint32_t (*readf)(x86mem_t *mem,uint32_t addr,int size),
+ void (*writef)(x86mem_t *mem,uint32_t addr,uint32_t val,int size))
+{
+ if (mem->data[X86MEM_REGION(chunkaddr)]) {
+ KFREE(mem->data[X86MEM_REGION(chunkaddr)]);
+ mem->data[X86MEM_REGION(chunkaddr)] = NULL;
+ }
+ mem->read[X86MEM_REGION(chunkaddr)] = readf;
+ mem->write[X86MEM_REGION(chunkaddr)] = writef;
+}
+
+/* *********************************************************************
+ * X86MEM_HOOK_RANGE(mem,addr,size,readf,writef)
+ *
+ * Establish a hook for a block of simulated memory
+ *
+ * Input parameters:
+ * mem - x86mem object
+ * addr - address in memory, should be aligned on a "chunk"
+ * boundary.
+ * size - size of region to hook. Should be a multiple
+ * of the chunk size
+ * readf - function to call on READ accesses
+ * writef - function to call on WRITE accesses
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void x86mem_hook_range(x86mem_t *mem,uint32_t chunkaddr,int size,
+ uint32_t (*readf)(x86mem_t *mem,uint32_t addr,int size),
+ void (*writef)(x86mem_t *mem,uint32_t addr,uint32_t val,int size))
+{
+ while (size > 0) {
+ x86mem_hook(mem,chunkaddr,readf,writef);
+ size -= X86MEM_CHUNKSIZE;
+ chunkaddr += X86MEM_CHUNKSIZE;
+ }
+}
+
diff --git a/cfe/cfe/pccons/x86mem.h b/cfe/cfe/pccons/x86mem.h
new file mode 100644
index 0000000..ed9132b
--- /dev/null
+++ b/cfe/cfe/pccons/x86mem.h
@@ -0,0 +1,109 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * X86 simulator sparse memory File: X86MEM.H
+ *
+ * This module implements X86 memory for the X86 emulator
+ * used by the BIOS simulator. To avoid allocating the
+ * entire 1MB of PC's addressable memory, this is a "sparse"
+ * memory model, allocating chunks of storage as needed.
+ * VGA BIOSes seem to do all sorts of bizarre things to memory
+ * so this helps reduce the total amount we need to allocate
+ * significantly.
+ *
+ * In addition, this module lets the simulator "hook"
+ * ranges of memory to be handled by a callback
+ * routine. This is used so that we can redirect
+ * accesses to VGA memory space to the PCI bus handler.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define X86MEM_CHUNKBITS 15
+#define X86MEM_ADDRESSBITS 20
+#define X86MEM_CHUNKSIZE (1<<X86MEM_CHUNKBITS)
+#define X86MEM_CHUNKS (1<<(X86MEM_ADDRESSBITS-X86MEM_CHUNKBITS))
+#define X86MEM_REGION(addr) (((addr) >> X86MEM_CHUNKBITS) & (X86MEM_CHUNKS-1))
+#define X86MEM_OFFSET(addr) ((addr) & (X86MEM_CHUNKSIZE-1))
+
+#define M_BYTE 1
+#define M_WORD 2
+#define M_DWORD 4
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef struct x86mem_s {
+ uint8_t *data[X86MEM_CHUNKS];
+ uint32_t (*read[X86MEM_CHUNKS])(struct x86mem_s *x86mem,
+ uint32_t addr,int size);
+ void (*write[X86MEM_CHUNKS])(struct x86mem_s *x86mem,
+ uint32_t addr,uint32_t val,int size);
+} x86mem_t;
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+void x86mem_init(x86mem_t *mem);
+void x86mem_uninit(x86mem_t *mem);
+
+
+uint8_t x86mem_readb(x86mem_t *mem,uint32_t addr);
+uint16_t x86mem_readw(x86mem_t *mem,uint32_t addr);
+uint32_t x86mem_readl(x86mem_t *mem,uint32_t addr);
+
+
+void x86mem_writeb(x86mem_t *mem,uint32_t addr,uint8_t data);
+void x86mem_writew(x86mem_t *mem,uint32_t addr,uint16_t data);
+void x86mem_writel(x86mem_t *mem,uint32_t addr,uint32_t data);
+void x86mem_memcpy(x86mem_t *mem,uint32_t destaddr,uint8_t *src,int count);
+void x86mem_hook(x86mem_t *mem,uint32_t chunkaddr,
+ uint32_t (*readf)(x86mem_t *mem,uint32_t addr,int size),
+ void (*writef)(x86mem_t *mem,uint32_t addr,uint32_t val,int size));
+void x86mem_hook_range(x86mem_t *mem,uint32_t chunkaddr,int size,
+ uint32_t (*readf)(x86mem_t *mem,uint32_t addr,int size),
+ void (*writef)(x86mem_t *mem,uint32_t addr,uint32_t val,int size));
+
diff --git a/cfe/cfe/pci/cfe_pci.h b/cfe/cfe/pci/cfe_pci.h
new file mode 100644
index 0000000..8780a6f
--- /dev/null
+++ b/cfe/cfe/pci/cfe_pci.h
@@ -0,0 +1,52 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * PCI definitions File: cfe_pci.h
+ *
+ * This file includes other files and defines macros to make
+ * our environment match that of the PCI configuration code
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+
+#define panic(x) printf(x)
diff --git a/cfe/cfe/pci/devlist2h.awk b/cfe/cfe/pci/devlist2h.awk
new file mode 100644
index 0000000..1f0b9b4
--- /dev/null
+++ b/cfe/cfe/pci/devlist2h.awk
@@ -0,0 +1,220 @@
+#! /usr/bin/awk -f
+# $NetBSD: devlist2h.awk,v 1.2 1996/01/22 21:08:09 cgd Exp $
+#
+# Copyright (c) 1995, 1996 Christopher G. Demetriou
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. 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.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by Christopher G. Demetriou.
+# 4. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+#
+BEGIN {
+ nproducts = nvendors = 0
+ dfile="pcidevs_data.h"
+ hfile="pcidevs.h"
+}
+NR == 1 {
+ VERSION = $0
+ gsub("\\$", "", VERSION)
+
+ printf("/*\n") > dfile
+ printf(" * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.\n") \
+ > dfile
+ printf(" *\n") > dfile
+ printf(" * generated from:\n") > dfile
+ printf(" *\t%s\n", VERSION) > dfile
+ printf(" */\n") > dfile
+
+ printf("/*\n") > hfile
+ printf(" * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.\n") \
+ > hfile
+ printf(" *\n") > hfile
+ printf(" * generated from:\n") > hfile
+ printf(" *\t%s\n", VERSION) > hfile
+ printf(" */\n") > hfile
+
+ next
+}
+$1 == "vendor" {
+ nvendors++
+
+ vendorindex[$2] = nvendors; # record index for this name, for later.
+ vendors[nvendors, 1] = $2; # name
+ vendors[nvendors, 2] = $3; # id
+ printf("#define\tPCI_VENDOR_%s\t%s\t", vendors[nvendors, 1],
+ vendors[nvendors, 2]) > hfile
+
+ i = 3; f = 4;
+
+ # comments
+ ocomment = oparen = 0
+ if (f <= NF) {
+ printf("\t/* ") > hfile
+ ocomment = 1;
+ }
+ while (f <= NF) {
+ if ($f == "#") {
+ printf("(") > hfile
+ oparen = 1
+ f++
+ continue
+ }
+ if (oparen) {
+ printf("%s", $f) > hfile
+ if (f < NF)
+ printf(" ") > hfile
+ f++
+ continue
+ }
+ vendors[nvendors, i] = $f
+ printf("%s", vendors[nvendors, i]) > hfile
+ if (f < NF)
+ printf(" ") > hfile
+ i++; f++;
+ }
+ if (oparen)
+ printf(")") > hfile
+ if (ocomment)
+ printf(" */") > hfile
+ printf("\n") > hfile
+
+ next
+}
+$1 == "product" {
+ nproducts++
+
+ products[nproducts, 1] = $2; # vendor name
+ products[nproducts, 2] = $3; # product id
+ products[nproducts, 3] = $4; # id
+ printf("#define\tPCI_PRODUCT_%s_%s\t%s\t", products[nproducts, 1],
+ products[nproducts, 2], products[nproducts, 3]) > hfile
+
+ i=4; f = 5;
+
+ # comments
+ ocomment = oparen = 0
+ if (f <= NF) {
+ printf("\t/* ") > hfile
+ ocomment = 1;
+ }
+ while (f <= NF) {
+ if ($f == "#") {
+ printf("(") > hfile
+ oparen = 1
+ f++
+ continue
+ }
+ if (oparen) {
+ printf("%s", $f) > hfile
+ if (f < NF)
+ printf(" ") > hfile
+ f++
+ continue
+ }
+ products[nproducts, i] = $f
+ printf("%s", products[nproducts, i]) > hfile
+ if (f < NF)
+ printf(" ") > hfile
+ i++; f++;
+ }
+ if (oparen)
+ printf(")") > hfile
+ if (ocomment)
+ printf(" */") > hfile
+ printf("\n") > hfile
+
+ next
+}
+{
+ if ($0 == "")
+ blanklines++
+ print $0 > hfile
+ if (blanklines < 2)
+ print $0 > dfile
+}
+END {
+ # print out the match tables
+
+ printf("\n") > dfile
+
+
+ printf("static const struct pci_knowndev pci_knowndevs[] = {\n") > dfile
+ for (i = 1; i <= nproducts; i++) {
+ printf("\t{\n") > dfile
+ printf("\t PCI_VENDOR_%s, PCI_PRODUCT_%s_%s,\n",
+ products[i, 1], products[i, 1], products[i, 2]) \
+ > dfile
+ printf("\t ") > dfile
+ printf("0") > dfile
+ printf(",\n") > dfile
+
+ vendi = vendorindex[products[i, 1]];
+ printf("\t \"") > dfile
+ j = 3;
+ needspace = 0;
+ while (vendors[vendi, j] != "") {
+ if (needspace)
+ printf(" ") > dfile
+ printf("%s", vendors[vendi, j]) > dfile
+ needspace = 1
+ j++
+ }
+ printf("\",\n") > dfile
+
+ printf("\t \"") > dfile
+ j = 4;
+ needspace = 0;
+ while (products[i, j] != "") {
+ if (needspace)
+ printf(" ") > dfile
+ printf("%s", products[i, j]) > dfile
+ needspace = 1
+ j++
+ }
+ printf("\",\n") > dfile
+ printf("\t},\n") > dfile
+ }
+ for (i = 1; i <= nvendors; i++) {
+ printf("\t{\n") > dfile
+ printf("\t PCI_VENDOR_%s, 0,\n", vendors[i, 1]) \
+ > dfile
+ printf("\t PCI_KNOWNDEV_NOPROD,\n") \
+ > dfile
+ printf("\t \"") > dfile
+ j = 3;
+ needspace = 0;
+ while (vendors[i, j] != "") {
+ if (needspace)
+ printf(" ") > dfile
+ printf("%s", vendors[i, j]) > dfile
+ needspace = 1
+ j++
+ }
+ printf("\",\n") > dfile
+ printf("\t NULL,\n") > dfile
+ printf("\t},\n") > dfile
+ }
+ printf("\t{ 0, 0, 0, NULL, NULL, }\n") > dfile
+ printf("};\n") > dfile
+}
diff --git a/cfe/cfe/pci/ldtinit.c b/cfe/cfe/pci/ldtinit.c
new file mode 100644
index 0000000..26025af
--- /dev/null
+++ b/cfe/cfe/pci/ldtinit.c
@@ -0,0 +1,641 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * LDT Fabric Initialization File: ldtinit.c
+ *
+ *********************************************************************
+ *
+ * Copyright 2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+/*
+ * Copyright 2001,2002
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions as
+ * they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. Neither the "Broadcom
+ * Corporation" name nor any trademark or logo of Broadcom
+ * Corporation may be used to endorse or promote products
+ * derived from this software without the prior written
+ * permission of Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * ldtinit.c: generic LDT fabric initialization and capability
+ * management.
+ */
+
+#include "lib_types.h"
+#include "lib_printf.h"
+#include "cfe_timer.h"
+
+#include "pcivar.h"
+#include "pcireg.h"
+#include "ldtreg.h"
+
+/* Write-to-clear bit masks */
+
+#if CFG_LDT_REV_017 /* XXX not really the right test */
+#define LDT_LINKCTRL_WC (LDT_LINKCTRL_CRCERROR_MASK)
+#else
+#define LDT_LINKCTRL_WC (LDT_LINKCTRL_LINKFAIL | LDT_LINKCTRL_CRCERROR_MASK)
+#endif
+
+
+/* LDT capability lookup. */
+
+unsigned
+pci_find_ldt_cap (pcitag_t tag, int secondary)
+{
+ pcireg_t cpr;
+ pcireg_t cr;
+ int offset, prev;
+ int type;
+
+ cpr = pci_conf_read(tag, PCI_CAPLISTPTR_REG);
+ offset = PCI_CAPLIST_PTR(cpr) &~ 0x3;
+ prev = 0;
+
+ while (offset != 0 && offset != prev) {
+#if (LDT_DEBUG > 1)
+ pci_tagprintf(tag, "read cap offset %04x\n", offset);
+#endif
+ cr = pci_conf_read(tag, offset);
+ if (PCI_CAPLIST_CAP(cr) == PCI_CAP_LDT) {
+ type = LDT_COMMAND_TYPE(cr);
+ if (secondary && type == LDT_COMMAND_TYPE_HOST)
+ return offset;
+ if (!secondary && type == LDT_COMMAND_TYPE_SLAVE)
+ return offset;
+ }
+ prev = offset;
+ offset = PCI_CAPLIST_NEXT(cr) &~ 0x3;
+ }
+ return 0;
+}
+
+
+/* LDT utility functions, mostly for capabilities. */
+
+static pcireg_t
+ldt_get_link(pcitag_t tag, int offset, int index)
+{
+ return pci_conf_read(tag, offset + LDT_LINK_OFF(index));
+}
+
+static void
+ldt_set_link(pcitag_t tag, int offset, int index, pcireg_t lr)
+{
+ pci_conf_write(tag, offset + LDT_LINK_OFF(index), lr);
+}
+
+#if (LDT_DEBUG != 0)
+static void
+ldt_show_cap(pcitag_t tag, int offset, int secondary)
+{
+ printf(" Cmd %08x", pci_conf_read(tag, offset));
+ offset += 4;
+ printf(" Lnk0 %08x", pci_conf_read(tag, offset));
+ offset += 4;
+ if (!secondary) {
+ printf(" Lnk1 %08x", pci_conf_read(tag, offset));
+ offset += 4;
+ }
+ printf(" Freq0 %08x", pci_conf_read(tag, offset));
+ offset += 4;
+ if (!secondary) {
+ printf(" Freq1 %08x", pci_conf_read(tag, offset));
+ offset += 4;
+ }
+ printf("\n");
+}
+#else
+static void
+ldt_show_cap(pcitag_t tag, int offset, int secondary)
+{
+}
+#endif
+
+
+/* LDT bus initialization and sizing. */
+
+/* We expect the entire chain to be ready at approximately the same
+ time, but we add some delay here for possible node-to-node
+ differences.
+
+ Empirically, neither InitDone nor LinkFail is reported for an
+ unconnected link. Thus we do not expect the outgoing link of a
+ terminating tunnel node to become ready.
+
+ Also, CRC errors are observed to occur with InitDone, so link
+ errors do not necessarily force LinkFail.
+*/
+
+static int
+ldt_wait_ready (pcitag_t tag, int offset, int index)
+{
+ int count;
+ pcireg_t lr;
+ int linkerr;
+
+ linkerr = 0;
+ count = 0x10000; /* empirical */
+ do {
+ if (--count == 0)
+ return 1;
+ lr = ldt_get_link(tag, offset, index);
+ if ((lr & (LDT_LINKCTRL_LINKFAIL | LDT_LINKCTRL_CRCERROR_MASK)) != 0)
+ linkerr = 1;
+ } while ((lr & (LDT_LINKCTRL_INITDONE | LDT_LINKCTRL_LINKFAIL)) == 0);
+
+ return linkerr;
+}
+
+static void
+ldt_end_chain (pcitag_t tag, int offset, int index)
+{
+ pcireg_t lr, t;
+
+ lr = ldt_get_link(tag, offset, index);
+ lr |= LDT_LINKCTRL_EOC;
+ ldt_set_link(tag, offset, index, lr);
+ lr |= LDT_LINKCTRL_TXOFF;
+ ldt_set_link(tag, offset, index, lr);
+ t = ldt_get_link(tag, offset, index); /* push */
+}
+
+
+static uint16_t
+ldt_freq_cap (pcitag_t tag, int offset, int index)
+{
+ pcireg_t cmd, cr;
+ uint16_t freq_cap;
+
+ cmd = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF);
+ if (LDT_COMMAND_TYPE(cmd) == LDT_COMMAND_TYPE_HOST) {
+ cr = pci_conf_read(tag, offset + LDT_FREQ_OFF);
+ if (LDT_REVISION_ID(cr) == LDT_REV_017) {
+ /* REV 0.17 has restricted support for setting
+ frequencies. We assume that this is the host bridge in
+ pseudo-1.0x mode, in which case the desired maximum
+ frequency was left in the LDT_FREQ register and all
+ lower frequencies are supported. */
+ freq_cap = (1 << (LDT_LINKFREQ(cr) + 1)) - 1;
+ } else {
+ freq_cap = LDT_LINKFREQ_CAP(cr);
+ }
+ } else {
+ cr = pci_conf_read(tag, offset + LDT_FREQ0_OFF);
+ if (LDT_REVISION_ID(cr) == LDT_REV_017) {
+ /* REV 0.17 has restricted support for setting frequencies.
+ This is not the host bridge. What to do? XXX */
+ freq_cap = (1 << LDT_FREQ_200);
+ } else {
+ cr = pci_conf_read(tag, offset + LDT_FREQn_OFF(index));
+ freq_cap = LDT_LINKFREQ_CAP(cr);
+ }
+ }
+ return freq_cap;
+}
+
+static uint8_t
+ldt_max_freq (uint16_t freq_cap)
+{
+ unsigned ldt_freq;
+
+ /* 200 MHz (encoded as 1 << 0) is required for all devices */
+ freq_cap |= (1 << LDT_FREQ_200);
+
+ ldt_freq = 0;
+
+ while (freq_cap != 1) {
+ ldt_freq++;
+ freq_cap >>= 1;
+ }
+
+ return (ldt_freq >= LDT_FREQ_200 && ldt_freq <= LDT_FREQ_1000) ?
+ ldt_freq : LDT_FREQ_200;
+}
+
+static void
+ldt_set_freq (pcitag_t tag, int offset, int index, uint8_t freq)
+{
+ pcireg_t cmd, cr;
+
+ cmd = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF);
+ if (LDT_COMMAND_TYPE(cmd) == LDT_COMMAND_TYPE_HOST) {
+ cr = pci_conf_read(tag, offset + LDT_FREQ_OFF);
+ cr &=~ LDT_LINKFREQ_MASK;
+ cr |= (freq << LDT_LINKFREQ_SHIFT);
+ pci_conf_write(tag, offset + LDT_FREQ_OFF, cr);
+ } else {
+ cr = pci_conf_read(tag, offset + LDT_FREQn_OFF(index));
+ cr &=~ LDT_LINKFREQ_MASK;
+ cr |= (freq << LDT_LINKFREQ_SHIFT);
+ pci_conf_write(tag, offset + LDT_FREQn_OFF(index), cr);
+ }
+#if (LDT_DEBUG > 1)
+ pci_tagprintf(tag, "set link %d freq = %02x\n", index, freq);
+#endif
+}
+
+
+/* LDT fabric initialization. See LDT Spec, Section 13.3. */
+static int
+ldt_fabric_init (pcitag_t br_tag, int br_offset, int bus, pci_flags_t flags)
+{
+ int next_free_id;
+ pcitag_t prev_tag, tag;
+ int offset, prev_offset;
+ int link, prev_link;
+ uint16_t prev_cap;
+ pcireg_t cmd, lr, id, t;
+ int double_ended;
+ int linkerr;
+
+ prev_tag = br_tag; prev_offset = br_offset; prev_link = 0;
+ /* Since there is no direct peer-to-peer traffic, there is no
+ point in configuring a downstream link with more capability
+ than the current one. */
+ prev_cap = ldt_freq_cap(br_tag, br_offset, 0);
+
+ next_free_id = 1;
+ double_ended = 0;
+
+#if (LDT_DEBUG != 0)
+ printf("Link sizing for bus %d, bridge freq cap %04x\n",
+ bus, ldt_freq_cap(br_tag, br_offset, 0));
+#endif
+ for (;;) {
+
+ tag = pci_make_tag(bus, 0, 0);
+
+ id = pci_conf_read(tag, PCI_ID_REG);
+#if (LDT_DEBUG > 1)
+ pci_tagprintf(tag, "ldt_fabric_init: id register %08x\n", id);
+#endif
+ if (PCI_VENDOR(id) == 0xffff) {
+ /* The incoming link had InitDone set, but we got an NXA
+ trying to read the vendor id. Either the reverse link
+ is broken or we have found an LDT-Lite node. For now,
+ assume the latter. Since an LDT-Lite device cannot be
+ a tunnel, assume the chain terminates here. */
+ pci_tagprintf(tag, "assumed LDT-LITE device (virtual unit %d)\n",
+ next_free_id);
+ break;
+ }
+
+ offset = pci_find_ldt_cap(tag, LDT_PRIMARY);
+#if (LDT_DEBUG > 1)
+ pci_tagprintf(tag, "ldt_fabric_init: offset %08x\n", offset);
+#endif
+ if (offset == 0) {
+ /* There is no primary interface; we must have found a host. */
+ offset = pci_find_ldt_cap(tag, LDT_SECONDARY);
+ if (offset != 0) {
+ lr = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF);
+ lr |= LDT_COMMAND_DOUBLE_ENDED;
+ pci_conf_write(tag, offset + LDT_COMMAND_CAP_OFF, lr);
+ double_ended = 1;
+ }
+ break;
+ }
+
+ /* Otherwise, we have the primary interface. */
+
+ /* Rewrite the old value to set master host bit. */
+ cmd = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF);
+#if (LDT_DEBUG > 1)
+ pci_tagprintf(tag, "ldt_fabric_init: set master host\n");
+#endif
+ pci_conf_write(tag, offset + LDT_COMMAND_CAP_OFF, cmd);
+ cmd = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF); /* push */
+
+ id = pci_conf_read(tag, PCI_ID_REG);
+
+ /* Update the unit id, gingerly. */
+ cmd &= ~LDT_COMMAND_UNIT_ID_MASK;
+ cmd |= (next_free_id << LDT_COMMAND_UNIT_ID_SHIFT);
+#if (LDT_DEBUG != 0)
+ pci_tagprintf(tag, "ldt_fabric_init: set unit id %d\n", next_free_id);
+#endif
+ if (!pci_conf_write_acked(tag, offset + LDT_COMMAND_CAP_OFF, cmd)) {
+ pci_tagprintf(tag, "no ack of id update to %d\n", next_free_id);
+ }
+
+ /* The unit id just changed. Update the tag */
+ tag = pci_make_tag(bus, next_free_id, 0);
+#if (LDT_DEBUG > 1)
+ pci_tagprintf(tag, "ldt_fabric_init: check unit id\n");
+#endif
+ t = pci_conf_read(tag, PCI_ID_REG);
+ if (t != id) {
+ pci_tagprintf(tag, "id mismatch: old %08x, new %08x\n", id, t);
+ }
+
+ next_free_id += LDT_COMMAND_UNIT_COUNT(cmd);
+
+ link = LDT_COMMAND_MASTER_HOST(cmd); /* Upstream link index */
+
+ /* LDT Rev 0.17 does not support frequency updates. */
+ if ((flags & PCI_FLG_LDT_REV_017) == 0) {
+ /* Find common frequency for upstream link. */
+ uint16_t link_cap, freq_cap_in, freq_cap_out;
+ uint8_t ldt_freq;
+
+ freq_cap_out = ldt_freq_cap(prev_tag, prev_offset, prev_link);
+ freq_cap_in = ldt_freq_cap(tag, offset, link);
+ link_cap = freq_cap_in & freq_cap_out;
+ ldt_freq = ldt_max_freq(link_cap & prev_cap);
+
+#if (LDT_DEBUG != 0)
+ pci_tagprintf(tag, "set freq %d\n", ldt_freq);
+#endif
+ /* Set up frequency registers, next warm reset installs. */
+ ldt_set_freq(prev_tag, prev_offset, prev_link, ldt_freq);
+ ldt_set_freq(tag, offset, link, ldt_freq);
+
+ prev_cap &= link_cap;
+ }
+
+ link ^= 1; /* Downstream */
+ linkerr = ldt_wait_ready(tag, offset, link);
+ lr = ldt_get_link(tag, offset, link);
+ ldt_set_link(tag, offset, link, lr | LDT_LINKCTRL_WC);
+
+#if (LDT_DEBUG != 0)
+ pci_tagprintf(tag, "node: up %d down %d:\n", link ^ 1, link);
+#endif
+ ldt_show_cap(tag, offset, LDT_PRIMARY);
+
+ if (linkerr || next_free_id > 0x1f) {
+ /* No downstream link or too many devices, set end of chain */
+ ldt_end_chain(tag, offset, link);
+ break;
+ }
+
+ prev_tag = tag; prev_offset = offset; prev_link = link;
+ }
+
+ return double_ended;
+}
+
+
+static int
+ldt_fabric_reinit (int bus)
+{
+ int next_free_id;
+ pcitag_t tag;
+ int offset;
+ int link;
+ pcireg_t cmd, lr, id, t;
+ int linkerr;
+
+ next_free_id = 1;
+
+#if (LDT_DEBUG != 0)
+ printf("Link resizing for bus %d\n", bus);
+#endif
+ for (;;) {
+
+ tag = pci_make_tag(bus, 0, 0);
+
+ id = pci_conf_read(tag, PCI_ID_REG);
+ if (PCI_VENDOR(id) == 0xffff) {
+ /* Per the init pass, assume this indicates a link to an
+ LDT-Lite node, and the chain terminates here. */
+ break;
+ }
+
+ offset = pci_find_ldt_cap(tag, LDT_PRIMARY);
+ if (offset == 0) {
+ /* There is no primary interface; we must have found a host. */
+ offset = pci_find_ldt_cap(tag, LDT_SECONDARY);
+ if (offset != 0) {
+ lr = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF);
+ lr |= LDT_COMMAND_DOUBLE_ENDED;
+ pci_conf_write(tag, offset + LDT_COMMAND_CAP_OFF, lr);
+ }
+ break;
+ }
+
+ /* Otherwise, we have the primary interface. */
+
+ /* Rewrite the old value to set master host bit. */
+ cmd = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF);
+ pci_conf_write(tag, offset + LDT_COMMAND_CAP_OFF, cmd);
+ cmd = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF);
+
+ id = pci_conf_read(tag, PCI_ID_REG);
+
+ /* (Re)update the unit id. See above. */
+ cmd &= ~LDT_COMMAND_UNIT_ID_MASK;
+ cmd |= (next_free_id << LDT_COMMAND_UNIT_ID_SHIFT);
+ if (!pci_conf_write_acked(tag, offset + LDT_COMMAND_CAP_OFF, cmd)) {
+ pci_tagprintf(tag, "no ack of id update to %d\n", next_free_id);
+ }
+
+ /* The unit id just changed. Update the tag */
+ tag = pci_make_tag(bus, next_free_id, 0);
+ t = pci_conf_read(tag, PCI_ID_REG); /* for good measure */
+ if (t != id) {
+ pci_tagprintf(tag, "id mismatch: old %08x, new %08x\n", id, t);
+ }
+
+ next_free_id += LDT_COMMAND_UNIT_COUNT(cmd);
+
+ link = LDT_COMMAND_MASTER_HOST(cmd); /* Upstream link index */
+ link ^= 1; /* Downstream */
+
+ linkerr = ldt_wait_ready(tag, offset, link);
+
+ lr = ldt_get_link(tag, offset, link);
+ ldt_set_link(tag, offset, link, lr | LDT_LINKCTRL_WC);
+#if (LDT_DEBUG > 1)
+ pci_tagprintf(tag, "node: up %d down %d:\n", link ^ 1, link);
+ ldt_show_cap(tag, offset, LDT_PRIMARY);
+#endif
+ if (linkerr || next_free_id > 0x1f) {
+ /* No downstream link or too many devices, set end of chain */
+ ldt_end_chain(tag, offset, link);
+ break;
+ }
+ }
+ return next_free_id - 1;
+}
+
+
+/* LDT link reset (warm or cold as set by caller) */
+
+void
+ldt_link_reset (pcitag_t tag, int delay)
+{
+ pcireg_t brctl;
+
+ /* This code may be necessary for LDT buses behind bridges (none
+ of which yet exist) but seems to be a bad idea for the SB-1250
+ LDT bus in pass 1 parts. Note that if we do reset, we must
+ delay to give any attached devices a chance to (re)initialize
+ per the PCI spec. */
+
+ /* Attempt a Secondary Bus Reset. */
+ brctl = pci_conf_read(tag, PPB_BRCTL_INTERRUPT_REG);
+ brctl |= PPB_BRCTL_SECONDARY_RESET;
+ pci_conf_write(tag, PPB_BRCTL_INTERRUPT_REG, brctl);
+
+ brctl = pci_conf_read(tag, PPB_BRCTL_INTERRUPT_REG);
+ if ((brctl & PPB_BRCTL_SECONDARY_RESET) != 0) {
+ int i;
+ /* Bit can be written, assume soft reset is implemented. */
+ brctl &=~ PPB_BRCTL_SECONDARY_RESET;
+ pci_conf_write(tag, PPB_BRCTL_INTERRUPT_REG, brctl);
+
+ /* Add some delay (duration is a guess) */
+ for (i = 0; i < delay; i++)
+ (void)pci_conf_read(tag, PPB_BRCTL_INTERRUPT_REG);
+ /* Alternatively, wait for LinkFail or InitDone. */
+ }
+}
+
+
+/* LDT bridge and fabric initialization for a secondary chain */
+
+int
+ldt_chain_init (pcitag_t tag, int bus, pci_flags_t flags)
+{
+ int offset;
+ int double_ended;
+ int linkerr;
+ pcireg_t cr, lr;
+ int ndev, no_probe;
+
+#if 0
+ /* This code may be necessary for LDT buses behind bridges (none
+ of which yet exist) but seems to be a bad idea for the SB-1250
+ LDT bus in pass 1 parts. Note that if we do reset, we must
+ delay to give any attached devices a chance to (re)initialize
+ per the PCI spec. */
+
+ /* Attempt a Secondary Bus Reset. */
+ ldt_link_reset(tag, 100);
+#endif /* 0 */
+
+ /* To avoid a chip erratum, we must prevent Type 0 configuration
+ probes that get NXAs on a double hosted chain. */
+ no_probe = 0;
+
+ offset = pci_find_ldt_cap(tag, LDT_SECONDARY);
+ if (offset != 0) {
+ linkerr = ldt_wait_ready(tag, offset, 0);
+
+#if (LDT_DEBUG > 1)
+ pci_tagprintf(tag, "bridge secondary:\n");
+ ldt_show_cap(tag, offset, LDT_SECONDARY);
+#endif
+ if (linkerr) {
+ pci_tagprintf(tag, "secondary bad or never ready\n");
+ } else {
+ lr = ldt_get_link(tag, offset, 0);
+ if ((lr & LDT_LINKCTRL_INITDONE) != 0)
+ double_ended = ldt_fabric_init(tag, offset, bus, flags);
+ else {
+ ldt_end_chain(tag, offset, 0);
+ double_ended = 0;
+ }
+ cr = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF);
+ if (double_ended)
+ cr |= LDT_COMMAND_DOUBLE_ENDED;
+ else
+ cr &=~ LDT_COMMAND_DOUBLE_ENDED;
+ pci_conf_write(tag, offset + LDT_COMMAND_CAP_OFF, cr);
+
+ /* Rev 0.17 does not support dynamic link resizing. */
+ if ((flags & PCI_FLG_LDT_REV_017) == 0) {
+ /* Issue a warm reset to update link frequencies. */
+ cr = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF);
+ cr |= LDT_COMMAND_WARM_RESET;
+ pci_conf_write(tag, offset + LDT_COMMAND_CAP_OFF, cr);
+ cr = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF);
+ ldt_link_reset(tag, 100);
+ ldt_wait_ready(tag, offset, 0);
+
+#if (LDT_DEBUG > 1)
+ pci_tagprintf(tag, "bridge secondary:\n");
+ ldt_show_cap(tag, offset, LDT_SECONDARY);
+#endif
+ /* After reset, let secondary devices reinitialize. */
+ cfe_sleep(CFE_HZ/2);
+
+ ndev = ldt_fabric_reinit(bus);
+
+ if (double_ended) {
+ cr = pci_conf_read(tag, offset + LDT_COMMAND_CAP_OFF);
+ cr |= LDT_COMMAND_DOUBLE_ENDED;
+ pci_conf_write(tag, offset + LDT_COMMAND_CAP_OFF, cr);
+
+ /* Bug workaround -- don't scan simple dual-hosted chain */
+ if (ndev == 0)
+ no_probe = 1;
+ }
+ }
+ }
+ }
+
+ return no_probe;
+}
diff --git a/cfe/cfe/pci/ldtreg.h b/cfe/cfe/pci/ldtreg.h
new file mode 100644
index 0000000..140effe
--- /dev/null
+++ b/cfe/cfe/pci/ldtreg.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2000,2001
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions as
+ * they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. Neither the "Broadcom
+ * Corporation" name nor any trademark or logo of Broadcom
+ * Corporation may be used to endorse or promote products
+ * derived from this software without the prior written
+ * permission of Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LDTREG_H_
+#define _LDTREG_H_
+
+/*
+ * LDT capability register definitions and macros.
+ * Derived from Revison 0.17 of the LDT (now HyperTransport)
+ * Specification with some 1.02/1.03 features.
+ *
+ * Note: Register and field definitions assume 32-bit register accesses.
+ */
+
+/*
+ * LDT Capability registers (identified by offsets within the capability)
+ */
+
+/*
+ * Command Register; contains command and capability fields.
+ */
+#define LDT_COMMAND_CAP_OFF 0x00
+
+#define LDT_CAP_ID_MASK 0x000000ff
+#define LDT_CAP_ID_SHIFT 0
+#define LDT_CAP_PTR_MASK 0x0000ff00
+#define LDT_CAP_PTR_SHIFT 8
+
+#define LDT_COMMAND_MASK 0xffff0000
+#define LDT_COMMAND_SHIFT 16
+#define LDT_COMMAND(cmd) \
+ (((cmd) & LDT_COMMAND_MASK) >> LDT_COMMAND_SHIFT)
+#define LDT_COMMAND_TYPE_MASK 0xe0000000
+#define LDT_COMMAND_TYPE_SHIFT (16+13)
+#define LDT_COMMAND_TYPE(cmd) \
+ (((cmd) & LDT_COMMAND_TYPE_MASK) >> LDT_COMMAND_TYPE_SHIFT)
+#define LDT_COMMAND_TYPE_SLAVE 0x0
+#define LDT_COMMAND_TYPE_HOST 0x1
+#define LDT_COMMAND_TYPE_IDC 0x4
+#define LDT_COMMAND_TYPE_AMAP 0x5
+/* Following for 1.0x only */
+#define LDT_COMMAND_DROP_ON_INIT 0x10000000
+
+/*
+ * An LDT capability for type Slave (aka Primary, aka "tunnel") consists
+ * of a Command register, two Link registers, and two Freq/Rev registers.
+ */
+/* Slave/Primary commands */
+#define LDT_COMMAND_UNIT_ID_MASK 0x001f0000
+#define LDT_COMMAND_UNIT_ID_SHIFT (16+0)
+#define LDT_COMMAND_UNIT_ID(cmd) \
+ (((cmd) & LDT_COMMAND_UNIT_ID_MASK) >> LDT_COMMAND_UNIT_ID_SHIFT)
+#define LDT_COMMAND_UNIT_COUNT_MASK 0x03e00000
+#define LDT_COMMAND_UNIT_COUNT_SHIFT (16+5)
+#define LDT_COMMAND_UNIT_COUNT(cmd) \
+ (((cmd) & LDT_COMMAND_UNIT_COUNT_MASK) >> LDT_COMMAND_UNIT_COUNT_SHIFT)
+#define LDT_COMMAND_MASTER_HOST_MASK 0x04000000
+#define LDT_COMMAND_MASTER_HOST(cmd) \
+ (((cmd) & LDT_COMMAND_MASTER_HOST_MASK) ? 1 : 0)
+#define LDT_COMMAND_DEFAULT_DIRECTION_MASK 0x08000000
+#define LDT_COMMAND_DEFAULT_DIRECTION(cmd) \
+ (((cmd) & LDT_COMMAND_DEFAULT_DIRECTION_MASK) ? 1 : 0)
+
+/*
+ * An LDT capability for type Host (aka Secondary) consists of a
+ * Command register, a single Link register, and a Freq/Rev register.
+ */
+/* Host/Secondary command fields */
+#define LDT_COMMAND_WARM_RESET 0x00010000
+#define LDT_COMMAND_DOUBLE_ENDED 0x00020000
+#define LDT_COMMAND_DEVICE_NUMBER_MASK 0x007c0000
+#define LDT_COMMAND_DEVICE_NUMBER_SHIFT (16+2)
+/* Following for 1.0x only */
+#define LDT_COMMAND_CHAIN_SIDE 0x00800000
+#define LDT_COMMAND_HOST_HIDE 0x01000000
+#define LDT_COMMAND_ACT_AS_SLAVE 0x02000000
+#define LDT_COMMAND_INBOUND_EOC_ERROR 0x04000000
+
+
+/*
+ * Link Register; contains control and config fields.
+ */
+#define LDT_LINK_OFF(n) (0x04 + ((n)<<2))
+
+#define LDT_LINKCTRL_MASK 0x0000ffff
+#define LDT_LINKCTRL_SHIFT 0
+#define LDT_LINKCTRL(cr) \
+ (((cr) & LDT_LINKCTRL_MASK) >> LDT_LINKCTRL_SHIFT)
+#define LDT_LINKCTRL_CFLE 0x00000002
+#define LDT_LINKCTRL_CST 0x00000004
+#define LDT_LINKCTRL_CFE 0x00000008
+#define LDT_LINKCTRL_LINKFAIL 0x00000010
+#define LDT_LINKCTRL_INITDONE 0x00000020
+#define LDT_LINKCTRL_EOC 0x00000040
+#define LDT_LINKCTRL_TXOFF 0x00000080
+#define LDT_LINKCTRL_CRCERROR_MASK 0x00000f00
+#define LDT_LINKCTRL_CRCERROR_SHIFT 8
+#define LDT_LINKCTRL_ISOCEN 0x00001000
+#define LDT_LINKCTRL_LSEN 0x00002000
+/* Following for 1.0x only */
+#define LDT_LINKCTRL_EXTCTL 0x00004000
+
+#define LDT_LINKCFG_MASK 0xffff0000
+#define LDT_LINKCFG_SHIFT 16
+#define LDT_LINKCFG(cr) \
+ (((cr) & LDT_LINKCFG_MASK) >> LDT_LINKCFG_SHIFT)
+#define LDT_LINKCFG_MAX_WIDTH_IN(cr) \
+ (((cr) >> (16+0)) & 0xf)
+#define LDT_LINKCFG_MAX_WIDTH_OUT(cr) \
+ (((cr) >> (16+4)) & 0xf)
+#define LDT_LINKCFG_WIDTH_IN(cr) \
+ (((cr) >> (16+8)) & 0xf)
+#define LDT_LINKCFG_WIDTH_OUT(cr) \
+ (((cr) >> (16+12)) & 0xf)
+
+
+/*
+ * Link Frequency Register; contains version and frequency fields.
+ */
+#define LDT_LINKFREQ_CAP(cr) \
+ (((cr) >> 16) & 0xffff)
+
+#define LDT_LINKFREQ_MASK 0x00000f00
+#define LDT_LINKFREQ_SHIFT 8
+#define LDT_LINKFREQ(cr) \
+ (((cr) >> 8) & 0x0f)
+
+#define LDT_REVISION_ID(cr) \
+ (((cr) >> 0) & 0xff)
+
+#define LDT_REV_017 0x11
+#define LDT_REV_102 0x22
+
+/* Slave/Primary offsets */
+#define LDT_FREQ0_OFF 0x0c
+#define LDT_FREQ1_OFF 0x10
+#define LDT_FREQn_OFF(n) (0x0c + ((n)<<2))
+
+/* Host/Secondary offsets */
+#define LDT_FREQ_OFF 0x08
+
+#define LDT_FREQ_200 0x00
+#define LDT_FREQ_300 0x01
+#define LDT_FREQ_400 0x02
+#define LDT_FREQ_500 0x03
+#define LDT_FREQ_600 0x04
+#define LDT_FREQ_800 0x05
+#define LDT_FREQ_1000 0x06
+
+#endif /* _LDTREG_H_ */
diff --git a/cfe/cfe/pci/pci_machdep.h b/cfe/cfe/pci/pci_machdep.h
new file mode 100644
index 0000000..c8b57ec
--- /dev/null
+++ b/cfe/cfe/pci/pci_machdep.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2001,2002 SiByte, Inc. All rights reserved.
+ */
+
+#ifndef _PCI_MACHDEP_H_
+#define _PCI_MACHDEP_H_
+
+/*
+ * Machine-specific definitions for PCI autoconfiguration.
+ *
+ * See the comments in pci_machdep.c for more explanation.
+ */
+
+#include "lib_types.h"
+
+/*
+ * Address types, as integers.
+ */
+
+typedef uint32_t pci_addr_t;
+typedef uint64_t phys_addr_t; /* ZBbus physical addresses. */
+
+/*
+ * Configuration tag; created from a {bus,device,function} triplet by
+ * pci_make_tag(), and passed to pci_conf_read() and pci_conf_write().
+ */
+typedef uint32_t pcitag_t;
+
+/*
+ * Type of a value read from or written to a configuration register.
+ * Always 32 bits.
+ */
+typedef uint32_t pcireg_t;
+
+#endif /* _PCI_MACHDEP_H_ */
diff --git a/cfe/cfe/pci/pci_subr.c b/cfe/cfe/pci/pci_subr.c
new file mode 100644
index 0000000..56c65b1
--- /dev/null
+++ b/cfe/cfe/pci/pci_subr.c
@@ -0,0 +1,710 @@
+/*
+ * Copyright (c) 1997 Zubin D. Dittia. All rights reserved.
+ * Copyright (c) 1995, 1996, 1998
+ * Christopher G. Demetriou. All rights reserved.
+ * Copyright (c) 1994 Charles M. Hannum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Charles M. Hannum.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * PCI autoconfiguration support functions.
+ */
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+#ifndef PCIVERBOSE
+# if CFG_MINIMAL_SIZE
+# define PCIVERBOSE 0
+# else
+# define PCIVERBOSE 1
+# endif
+#endif
+
+#include "pcireg.h"
+#include "pcivar.h"
+
+const char *pci_findvendor(pcireg_t id_reg);
+
+static void pci_conf_print_ids(pcireg_t rval, const char *prefix);
+static int pci_conf_print_bar (pcitag_t,
+ const pcireg_t *, int, const char *, int, int);
+
+/*
+ * Descriptions of known PCI classes and subclasses.
+ *
+ * Subclasses are described in the same way as classes, but have a
+ * NULL subclass pointer.
+ */
+struct pci_class {
+ char *name;
+ int val; /* as wide as pci_{,sub}class_t */
+ struct pci_class *subclasses;
+};
+
+struct pci_class pci_subclass_prehistoric[] = {
+ { "miscellaneous", PCI_SUBCLASS_PREHISTORIC_MISC, },
+ { "VGA", PCI_SUBCLASS_PREHISTORIC_VGA, },
+ { 0 }
+};
+
+struct pci_class pci_subclass_mass_storage[] = {
+ { "SCSI", PCI_SUBCLASS_MASS_STORAGE_SCSI, },
+ { "IDE", PCI_SUBCLASS_MASS_STORAGE_IDE, },
+ { "floppy", PCI_SUBCLASS_MASS_STORAGE_FLOPPY, },
+ { "IPI", PCI_SUBCLASS_MASS_STORAGE_IPI, },
+ { "RAID", PCI_SUBCLASS_MASS_STORAGE_RAID, },
+ { "miscellaneous", PCI_SUBCLASS_MASS_STORAGE_MISC, },
+ { 0 },
+};
+
+struct pci_class pci_subclass_network[] = {
+ { "ethernet", PCI_SUBCLASS_NETWORK_ETHERNET, },
+ { "token ring", PCI_SUBCLASS_NETWORK_TOKENRING, },
+ { "FDDI", PCI_SUBCLASS_NETWORK_FDDI, },
+ { "ATM", PCI_SUBCLASS_NETWORK_ATM, },
+ { "ISDN", PCI_SUBCLASS_NETWORK_ISDN, },
+ { "WorldFip", PCI_SUBCLASS_NETWORK_WORLDFIP, },
+ { "PCMIG MultiComp", PCI_SUBCLASS_NETWORK_PCIMGMULTICOMP, },
+ { "miscellaneous", PCI_SUBCLASS_NETWORK_MISC, },
+ { 0 },
+};
+
+struct pci_class pci_subclass_display[] = {
+ { "VGA", PCI_SUBCLASS_DISPLAY_VGA, },
+ { "XGA", PCI_SUBCLASS_DISPLAY_XGA, },
+ { "3D", PCI_SUBCLASS_DISPLAY_3D, },
+ { "miscellaneous", PCI_SUBCLASS_DISPLAY_MISC, },
+ { 0 },
+};
+
+struct pci_class pci_subclass_multimedia[] = {
+ { "video", PCI_SUBCLASS_MULTIMEDIA_VIDEO, },
+ { "audio", PCI_SUBCLASS_MULTIMEDIA_AUDIO, },
+ { "telephony", PCI_SUBCLASS_MULTIMEDIA_TELEPHONY, },
+ { "miscellaneous", PCI_SUBCLASS_MULTIMEDIA_MISC, },
+ { 0 },
+};
+
+struct pci_class pci_subclass_memory[] = {
+ { "RAM", PCI_SUBCLASS_MEMORY_RAM, },
+ { "flash", PCI_SUBCLASS_MEMORY_FLASH, },
+ { "miscellaneous", PCI_SUBCLASS_MEMORY_MISC, },
+ { 0 },
+};
+
+struct pci_class pci_subclass_bridge[] = {
+ { "host", PCI_SUBCLASS_BRIDGE_HOST, },
+ { "ISA", PCI_SUBCLASS_BRIDGE_ISA, },
+ { "EISA", PCI_SUBCLASS_BRIDGE_EISA, },
+ { "MicroChannel", PCI_SUBCLASS_BRIDGE_MCA, },
+ { "PCI", PCI_SUBCLASS_BRIDGE_PCI, },
+ { "PCMCIA", PCI_SUBCLASS_BRIDGE_PCMCIA, },
+ { "NuBus", PCI_SUBCLASS_BRIDGE_NUBUS, },
+ { "CardBus", PCI_SUBCLASS_BRIDGE_CARDBUS, },
+ { "RACEway", PCI_SUBCLASS_BRIDGE_RACEWAY, },
+ { "Semi-transparent PCI", PCI_SUBCLASS_BRIDGE_STPCI, },
+ { "InfiniBand", PCI_SUBCLASS_BRIDGE_INFINIBAND, },
+ { "miscellaneous", PCI_SUBCLASS_BRIDGE_MISC, },
+ { 0 },
+};
+
+struct pci_class pci_subclass_communications[] = {
+ { "serial", PCI_SUBCLASS_COMMUNICATIONS_SERIAL, },
+ { "parallel", PCI_SUBCLASS_COMMUNICATIONS_PARALLEL, },
+ { "multi-port serial", PCI_SUBCLASS_COMMUNICATIONS_MPSERIAL, },
+ { "modem", PCI_SUBCLASS_COMMUNICATIONS_MODEM, },
+ { "miscellaneous", PCI_SUBCLASS_COMMUNICATIONS_MISC, },
+ { 0 },
+};
+
+struct pci_class pci_subclass_system[] = {
+ { "8259 PIC", PCI_SUBCLASS_SYSTEM_PIC, },
+ { "8237 DMA", PCI_SUBCLASS_SYSTEM_DMA, },
+ { "8254 timer", PCI_SUBCLASS_SYSTEM_TIMER, },
+ { "RTC", PCI_SUBCLASS_SYSTEM_RTC, },
+ { "PCI Hot-Plug", PCI_SUBCLASS_SYSTEM_PCIHOTPLUG, },
+ { "miscellaneous", PCI_SUBCLASS_SYSTEM_MISC, },
+ { 0 },
+};
+
+struct pci_class pci_subclass_input[] = {
+ { "keyboard", PCI_SUBCLASS_INPUT_KEYBOARD, },
+ { "digitizer", PCI_SUBCLASS_INPUT_DIGITIZER, },
+ { "mouse", PCI_SUBCLASS_INPUT_MOUSE, },
+ { "scanner", PCI_SUBCLASS_INPUT_SCANNER, },
+ { "game port", PCI_SUBCLASS_INPUT_GAMEPORT, },
+ { "miscellaneous", PCI_SUBCLASS_INPUT_MISC, },
+ { 0 },
+};
+
+struct pci_class pci_subclass_dock[] = {
+ { "generic", PCI_SUBCLASS_DOCK_GENERIC, },
+ { "miscellaneous", PCI_SUBCLASS_DOCK_MISC, },
+ { 0 },
+};
+
+struct pci_class pci_subclass_processor[] = {
+ { "386", PCI_SUBCLASS_PROCESSOR_386, },
+ { "486", PCI_SUBCLASS_PROCESSOR_486, },
+ { "Pentium", PCI_SUBCLASS_PROCESSOR_PENTIUM, },
+ { "Alpha", PCI_SUBCLASS_PROCESSOR_ALPHA, },
+ { "PowerPC", PCI_SUBCLASS_PROCESSOR_POWERPC, },
+ { "MIPS", PCI_SUBCLASS_PROCESSOR_MIPS, },
+ { "Co-processor", PCI_SUBCLASS_PROCESSOR_COPROC, },
+ { 0 },
+};
+
+struct pci_class pci_subclass_serialbus[] = {
+ { "Firewire", PCI_SUBCLASS_SERIALBUS_FIREWIRE, },
+ { "ACCESS.bus", PCI_SUBCLASS_SERIALBUS_ACCESS, },
+ { "SSA", PCI_SUBCLASS_SERIALBUS_SSA, },
+ { "USB", PCI_SUBCLASS_SERIALBUS_USB, },
+ /* XXX Fiber Channel/_FIBRECHANNEL */
+ { "Fiber Channel", PCI_SUBCLASS_SERIALBUS_FIBER, },
+ { "SMBus", PCI_SUBCLASS_SERIALBUS_SMBUS, },
+ { "InfiniBand", PCI_SUBCLASS_SERIALBUS_INFINIBAND, },
+ { "IPMI", PCI_SUBCLASS_SERIALBUS_IPMI, },
+ { "SERCOS", PCI_SUBCLASS_SERIALBUS_SERCOS, },
+ { "CANbus", PCI_SUBCLASS_SERIALBUS_CANBUS, },
+ { 0 },
+};
+
+struct pci_class pci_subclass_wireless[] = {
+ { "iRDA", PCI_SUBCLASS_WIRELESS_IRDA, },
+ { "Consumer IR", PCI_SUBCLASS_WIRELESS_CONSUMERIR, },
+ { "RF", PCI_SUBCLASS_WIRELESS_RF, },
+ { "miscellaneous", PCI_SUBCLASS_WIRELESS_MISC, },
+ { 0 },
+};
+
+struct pci_class pci_subclass_i2o[] = {
+ { "1.0", PCI_SUBCLASS_I2O_STANDARD, },
+ { 0 },
+};
+
+struct pci_class pci_subclass_satcom[] = {
+ { "TV", PCI_SUBCLASS_SATCOM_TV, },
+ { "audio", PCI_SUBCLASS_SATCOM_AUDIO, },
+ { "voice", PCI_SUBCLASS_SATCOM_VOICE, },
+ { "data", PCI_SUBCLASS_SATCOM_DATA, },
+ { 0 },
+};
+
+struct pci_class pci_subclass_crypto[] = {
+ { "network/computing", PCI_SUBCLASS_CRYPTO_NETCOMP, },
+ { "entertainment", PCI_SUBCLASS_CRYPTO_ENTERTAINMENT, },
+ { "miscellaneous", PCI_SUBCLASS_CRYPTO_MISC, },
+ { 0 },
+};
+
+struct pci_class pci_subclass_dasp[] = {
+ { "DPIO", PCI_SUBCLASS_DASP_DPIO, },
+ { "time and frequency", PCI_SUBCLASS_DASP_TIMERFREQ, },
+ { "miscellaneous", PCI_SUBCLASS_DASP_MISC, },
+ { 0 },
+};
+
+struct pci_class pci_class[] = {
+ { "prehistoric", PCI_CLASS_PREHISTORIC,
+ pci_subclass_prehistoric, },
+ { "mass storage", PCI_CLASS_MASS_STORAGE,
+ pci_subclass_mass_storage, },
+ { "network", PCI_CLASS_NETWORK,
+ pci_subclass_network, },
+ { "display", PCI_CLASS_DISPLAY,
+ pci_subclass_display, },
+ { "multimedia", PCI_CLASS_MULTIMEDIA,
+ pci_subclass_multimedia, },
+ { "memory", PCI_CLASS_MEMORY,
+ pci_subclass_memory, },
+ { "bridge", PCI_CLASS_BRIDGE,
+ pci_subclass_bridge, },
+ { "communications", PCI_CLASS_COMMUNICATIONS,
+ pci_subclass_communications, },
+ { "system", PCI_CLASS_SYSTEM,
+ pci_subclass_system, },
+ { "input", PCI_CLASS_INPUT,
+ pci_subclass_input, },
+ { "dock", PCI_CLASS_DOCK,
+ pci_subclass_dock, },
+ { "processor", PCI_CLASS_PROCESSOR,
+ pci_subclass_processor, },
+ { "serial bus", PCI_CLASS_SERIALBUS,
+ pci_subclass_serialbus, },
+ { "wireless", PCI_CLASS_WIRELESS,
+ pci_subclass_wireless, },
+ { "I2O", PCI_CLASS_I2O,
+ pci_subclass_i2o, },
+ { "satellite comm", PCI_CLASS_SATCOM,
+ pci_subclass_satcom, },
+ { "crypto", PCI_CLASS_CRYPTO,
+ pci_subclass_crypto, },
+ { "DASP", PCI_CLASS_DASP,
+ pci_subclass_dasp, },
+ { "undefined", PCI_CLASS_UNDEFINED,
+ 0, },
+ { 0 },
+};
+
+#if PCIVERBOSE
+/*
+ * Descriptions of of known vendors and devices ("products").
+ */
+#include "pcidevs.h"
+
+struct pci_knowndev2 {
+ pci_vendor_id_t vendor;
+ pci_product_id_t product;
+ int flags;
+ int vendorname, productname;
+};
+#define PCI_KNOWNDEV_NOPROD 0x01 /* match on vendor only */
+#include "pcidevs_data2.h"
+
+const char *
+pci_findvendor(pcireg_t id_reg)
+{
+ pci_vendor_id_t vendor = PCI_VENDOR(id_reg);
+ const struct pci_knowndev2 *kdp;
+
+ kdp = pci_knowndevs;
+ while (kdp->vendorname != PCI_STRING_NULL) { /* all have vendor name */
+ if (kdp->vendor == vendor)
+ break;
+ kdp++;
+ }
+ if (kdp->vendorname == PCI_STRING_NULL) return NULL;
+ return PCI_STRING(kdp->vendorname);
+}
+#else
+const char *
+pci_findvendor(pcireg_t id_reg)
+{
+ return NULL;
+}
+#endif /* PCIVERBOSE */
+
+void
+pci_devinfo(pcireg_t id_reg, pcireg_t class_reg, int showclass, char *cp)
+{
+ pci_vendor_id_t vendor;
+ pci_product_id_t product;
+ pci_class_t class;
+ pci_subclass_t subclass;
+ pci_interface_t interface;
+ pci_revision_t revision;
+ const char *vendor_namep, *product_namep;
+ struct pci_class *classp, *subclassp;
+#if PCIVERBOSE
+ const struct pci_knowndev2 *kdp;
+ const char *unmatched = "unknown ";
+#else
+ const char *unmatched = "";
+#endif
+
+ vendor = PCI_VENDOR(id_reg);
+ product = PCI_PRODUCT(id_reg);
+
+ class = PCI_CLASS(class_reg);
+ subclass = PCI_SUBCLASS(class_reg);
+ interface = PCI_INTERFACE(class_reg);
+ revision = PCI_REVISION(class_reg);
+
+#if PCIVERBOSE
+ kdp = pci_knowndevs;
+ while (kdp->vendorname != PCI_STRING_NULL) { /* all have vendor name */
+ if (kdp->vendor == vendor && (kdp->product == product ||
+ (kdp->flags & PCI_KNOWNDEV_NOPROD) != 0))
+ break;
+ kdp++;
+ }
+ if (kdp->vendorname == PCI_STRING_NULL)
+ vendor_namep = product_namep = NULL;
+ else {
+ vendor_namep = PCI_STRING(kdp->vendorname);
+ product_namep = ((kdp->flags & PCI_KNOWNDEV_NOPROD) == 0 ?
+ PCI_STRING(kdp->productname) : NULL);
+ }
+#else /* PCIVERBOSE */
+ vendor_namep = product_namep = NULL;
+#endif /* PCIVERBOSE */
+
+ classp = pci_class;
+ while (classp->name != NULL) {
+ if (class == classp->val)
+ break;
+ classp++;
+ }
+
+ subclassp = (classp->name != NULL) ? classp->subclasses : NULL;
+ while (subclassp && subclassp->name != NULL) {
+ if (subclass == subclassp->val)
+ break;
+ subclassp++;
+ }
+
+ if (vendor_namep == NULL)
+ cp += sprintf(cp, "%svendor 0x%04x product 0x%04x",
+ unmatched, vendor, product);
+ else if (product_namep != NULL)
+ cp += sprintf(cp, "%s %s", vendor_namep, product_namep);
+ else
+ cp += sprintf(cp, "%s product 0x%04x", vendor_namep, product);
+ if (showclass) {
+ cp += sprintf(cp, " (");
+ if (classp->name == NULL)
+ cp += sprintf(cp, "class 0x%02x, subclass 0x%02x",
+ class, subclass);
+ else {
+ if (subclassp == NULL || subclassp->name == NULL)
+ cp += sprintf(cp, "%s subclass 0x%02x",
+ classp->name, subclass);
+ else
+ cp += sprintf(cp, "%s %s", subclassp->name, classp->name);
+ }
+ if (interface != 0)
+ cp += sprintf(cp, ", interface 0x%02x", interface);
+ if (revision != 0)
+ cp += sprintf(cp, ", revision 0x%02x", revision);
+ cp += sprintf(cp, ")");
+ }
+}
+
+
+/*
+ * Support routines for printing out PCI configuration registers.
+ */
+
+#define i2o(i) ((i) * 4)
+#define o2i(o) ((o) / 4)
+#define onoff(str, bit) \
+ do { \
+ printf(" %s: %s\n", (str), (rval & (bit)) ? "on" : "off"); \
+ } while (0)
+
+#if PCIVERBOSE
+static void
+pci_conf_print_ids(pcireg_t rval, const char *prefix)
+{
+ const struct pci_knowndev2 *kdp;
+
+ for (kdp = pci_knowndevs; kdp->vendorname != PCI_STRING_NULL; kdp++) {
+ if (kdp->vendor == PCI_VENDOR(rval) &&
+ (kdp->product == PCI_PRODUCT(rval) ||
+ (kdp->flags & PCI_KNOWNDEV_NOPROD) != 0)) {
+ break;
+ }
+ }
+ if (kdp->vendorname != PCI_STRING_NULL)
+ printf("%sVendor Name: %s (0x%04x)\n", prefix,
+ PCI_STRING(kdp->vendorname), PCI_VENDOR(rval));
+ else
+ printf("%sVendor ID: 0x%04x\n", prefix, PCI_VENDOR(rval));
+ if (kdp->productname != PCI_STRING_NULL
+ && (kdp->flags & PCI_KNOWNDEV_NOPROD) == 0)
+ printf("%sDevice Name: %s (0x%04x)\n", prefix,
+ PCI_STRING(kdp->productname), PCI_PRODUCT(rval));
+ else
+ printf("%sDevice ID: 0x%04x\n", prefix, PCI_PRODUCT(rval));
+}
+#else
+static void
+pci_conf_print_ids(pcireg_t rval, const char *prefix)
+{
+ printf("%sVendor ID: 0x%04x\n", prefix, PCI_VENDOR(rval));
+ printf("%sDevice ID: 0x%04x\n", prefix, PCI_PRODUCT(rval));
+}
+#endif /* PCIVERBOSE */
+
+static int
+pci_conf_print_bar(
+ pcitag_t tag, const pcireg_t *regs,
+ int reg, const char *name,
+ int sizebar, int onlyimpl)
+{
+ int width;
+ pcireg_t mask, rval;
+ pcireg_t mask64h, rval64h;
+
+#ifdef __GNUC__ /* XXX GCC -Wuninitialized inadequacies */
+ mask64h = rval64h = 0;
+#endif
+
+ width = 4;
+
+ /*
+ * Section 6.2.5.1, `Address Maps', tells us that:
+ *
+ * 1) The builtin software should have already mapped the
+ * device in a reasonable way.
+ *
+ * 2) A device which wants 2^n bytes of memory will hardwire
+ * the bottom n bits of the address to 0. As recommended,
+ * we write all 1s and see what we get back.
+ */
+ rval = regs[o2i(reg)];
+ /* XXX don't size unknown memory type? */
+ if (rval != 0 && sizebar) {
+ uint32_t cmdreg;
+
+ /*
+ * The following sequence seems to make some devices
+ * (e.g. host bus bridges, which don't normally
+ * have their space mapped) very unhappy, to
+ * the point of crashing the system.
+ *
+ * Therefore, if the mapping register is zero to
+ * start out with, don't bother trying.
+ */
+
+ cmdreg = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
+ cmdreg &= (PCI_COMMAND_MASK << PCI_COMMAND_SHIFT); /* keep status */
+ pci_conf_write(tag, PCI_COMMAND_STATUS_REG,
+ cmdreg & ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE));
+
+ pci_conf_write(tag, reg, 0xffffffff);
+ mask = pci_conf_read(tag, reg);
+ pci_conf_write(tag, reg, rval);
+ if (PCI_MAPREG_TYPE(rval) == PCI_MAPREG_TYPE_MEM &&
+ PCI_MAPREG_MEM_TYPE(rval) == PCI_MAPREG_MEM_TYPE_64BIT) {
+ rval64h = regs[o2i(reg + 4)];
+ pci_conf_write(tag, reg + 4, 0xffffffff);
+ mask64h = pci_conf_read(tag, reg + 4);
+ pci_conf_write(tag, reg + 4, rval64h);
+ width = 8;
+ }
+
+ pci_conf_write(tag, PCI_COMMAND_STATUS_REG, cmdreg);
+ } else
+ mask = 0;
+
+ if (rval == 0 && onlyimpl)
+ return width;
+
+ printf(" Base Address Register at 0x%02x", reg);
+ if (name)
+ printf(" (%s)", name);
+ printf("\n ");
+ if (rval == 0) {
+ printf("not implemented(?)\n");
+ return width;
+ }
+ printf("type: ");
+ if (PCI_MAPREG_TYPE(rval) == PCI_MAPREG_TYPE_MEM) {
+ const char *type, *prefetch;
+
+ switch (PCI_MAPREG_MEM_TYPE(rval)) {
+ case PCI_MAPREG_MEM_TYPE_32BIT:
+ type = "32-bit";
+ break;
+ case PCI_MAPREG_MEM_TYPE_32BIT_1M:
+ type = "32-bit-1M";
+ break;
+ case PCI_MAPREG_MEM_TYPE_64BIT:
+ type = "64-bit";
+ break;
+ default:
+ type = "unknown (XXX)";
+ break;
+ }
+ if (PCI_MAPREG_MEM_PREFETCHABLE(rval))
+ prefetch = "";
+ else
+ prefetch = "non";
+ printf("%s %sprefetchable memory\n", type, prefetch);
+ switch (PCI_MAPREG_MEM_TYPE(rval)) {
+ case PCI_MAPREG_MEM_TYPE_64BIT:
+ printf(" base: 0x%016llx, ",
+ PCI_MAPREG_MEM64_ADDR(
+ ((((long long) rval64h) << 32) | rval)));
+ if (sizebar)
+ printf("size: 0x%016llx",
+ PCI_MAPREG_MEM64_SIZE(
+ ((((long long) mask64h) << 32) | mask)));
+ else
+ printf("not sized");
+ printf("\n");
+ break;
+ case PCI_MAPREG_MEM_TYPE_32BIT:
+ case PCI_MAPREG_MEM_TYPE_32BIT_1M:
+ default:
+ printf(" base: 0x%08x, ", PCI_MAPREG_MEM_ADDR(rval));
+ if (sizebar)
+ printf("size: 0x%08x", PCI_MAPREG_MEM_SIZE(mask));
+ else
+ printf("not sized");
+ printf("\n");
+ break;
+ }
+ } else {
+ if (sizebar)
+ printf("%d-bit ", mask & ~0x0000ffff ? 32 : 16);
+ printf("i/o\n");
+ printf(" base: 0x%08x, ", PCI_MAPREG_IO_ADDR(rval));
+ if (sizebar)
+ printf("size: 0x%08x", PCI_MAPREG_IO_SIZE(mask));
+ else
+ printf("not sized");
+ printf("\n");
+ }
+
+ return width;
+}
+
+
+/* Summary printing: Display device ID, status, memory map only. */
+
+#define on(str, bit) \
+ do { if (rval & (bit)) printf(" %s: on\n", (str)); } while (0)
+
+void
+pci_conf_print(pcitag_t tag)
+{
+ pcireg_t regs[o2i(256)];
+ int off, width;
+ pcireg_t rval;
+ uint32_t base, limit;
+ int sizebars;
+
+ if (!pci_probe_tag(tag)) {
+ printf("no device\n");
+ return;
+ }
+
+ for (off = 0; off < 256; off += 4)
+ regs[o2i(off)] = pci_conf_read(tag, off);
+
+ rval = regs[o2i(PCI_ID_REG)];
+ pci_conf_print_ids(rval, " ");
+
+ rval = regs[o2i(PCI_COMMAND_STATUS_REG)];
+
+ printf(" Command: 0x%04x\n", rval & 0xffff);
+ on("I/O space accesses", PCI_COMMAND_IO_ENABLE);
+ on("Memory space accesses", PCI_COMMAND_MEM_ENABLE);
+ on("Bus mastering", PCI_COMMAND_MASTER_ENABLE);
+
+ printf(" Status: 0x%04x\n", PCI_STATUS(rval));
+ on("Slave signaled Target Abort", PCI_STATUS_TARGET_TARGET_ABORT);
+ on("Master received Target Abort", PCI_STATUS_MASTER_TARGET_ABORT);
+ on("Master received Master Abort", PCI_STATUS_MASTER_ABORT);
+ on("Asserted System Error (SERR)", PCI_STATUS_SYSTEM_ERROR);
+ on("Parity error detected", PCI_STATUS_PARITY_DETECT);
+
+ switch (PCI_HDRTYPE_TYPE(regs[o2i(PCI_BHLC_REG)])) {
+ case 0:
+ /* Standard device header */
+ printf(" Type 0 (normal) header:\n");
+
+ /* sizing host BARs is often bad news */
+ sizebars = 1;
+ if (PCI_CLASS(regs[o2i(PCI_CLASS_REG)]) == PCI_CLASS_BRIDGE &&
+ PCI_SUBCLASS(regs[o2i(PCI_CLASS_REG)]) == PCI_SUBCLASS_BRIDGE_HOST)
+ sizebars = 0;
+ for (off = PCI_MAPREG_START; off < PCI_MAPREG_END; off += width)
+ width = pci_conf_print_bar(tag, regs, off, NULL, sizebars, 1);
+
+ rval = regs[o2i(PCI_BPARAM_INTERRUPT_REG)];
+ printf(" Interrupt Line: 0x%02x\n", PCI_INTERRUPT_LINE(rval));
+ break;
+
+ case 1:
+ /* PCI-PCI bridge header */
+ printf(" Type 1 (PCI-PCI bridge) header:\n");
+
+ rval = regs[o2i(PPB_BUSINFO_REG)];
+ printf(" Buses:\n");
+ printf(" Primary: %d,", PPB_BUSINFO_PRIMARY(rval));
+ printf(" Secondary: %d,", PPB_BUSINFO_SECONDARY(rval));
+ printf(" Subordinate: %d\n", PPB_BUSINFO_SUBORD(rval));
+
+ rval = regs[o2i(PPB_IO_STATUS_REG)];
+ printf(" Secondary Status: 0x%04x\n", PPB_SECSTATUS(rval));
+ on(" Data parity error detected", PCI_STATUS_PARITY_ERROR);
+ on(" Signaled Target Abort", PCI_STATUS_TARGET_TARGET_ABORT);
+ on(" Received Target Abort", PCI_STATUS_MASTER_TARGET_ABORT);
+ on(" Received Master Abort", PCI_STATUS_MASTER_ABORT);
+ on(" System Error", PCI_STATUS_SYSTEM_ERROR);
+ on(" Parity Error", PCI_STATUS_PARITY_DETECT);
+
+ rval = regs[o2i(PPB_IO_STATUS_REG)];
+ base = PPB_IO_BASE(rval);
+ limit = PPB_IO_LIMIT(rval);
+ if (base != 0 || limit != 0) {
+ printf(" I/O Range:\n");
+
+ if ((base & 0xf) != 0 || (limit & 0xf) != 0) {
+ base = ((base & 0xf0) << 8) | 0x000;
+ limit = ((limit & 0xf0) << 8) | 0xfff;
+ rval = regs[o2i(PPB_IO_UPPER_REG)];
+ base |= PPB_BASE(rval) << 16;
+ limit |= PPB_LIMIT(rval) << 16;
+ printf(" base: 0x%08x, limit: 0x%08x\n", base, limit);
+ } else {
+ base = (base << 8) | 0x000;
+ limit = (limit << 8) | 0xfff;
+ printf(" base: 0x%04x, limit: 0x%04x\n", base, limit);
+ }
+ }
+
+ base = PPB_BASE(regs[o2i(PPB_MEM_REG)]) & 0xfff0;
+ limit = PPB_LIMIT(regs[o2i(PPB_MEM_REG)]) & 0xfff0;
+ printf(" Memory Range:\n");
+ base = (base << 16) | 0x00000;
+ limit = (limit << 16) | 0xfffff;
+ printf(" base: 0x%08x, limit: 0x%08x\n", base, limit);
+
+ base = PPB_BASE(regs[o2i(PPB_PREFMEM_REG)]) & 0xffff;
+ limit = PPB_LIMIT(regs[o2i(PPB_PREFMEM_REG)]) & 0xffff;
+ if (base != 0 || limit != 0
+ || regs[o2i(PPB_PREFMEM_BASE_UPPER_REG)] != 0
+ || regs[o2i(PPB_PREFMEM_LIMIT_UPPER_REG)] != 0) {
+ printf(" Prefetchable Memory Range:\n");
+ if ((base & 0xf) != 0 || (limit & 0xf) != 0) {
+ base = ((base & 0xfff0) << 16) | 0x00000;
+ limit = ((limit & 0xfff0) << 16) | 0xfffff;
+ printf(" base: 0x%08x%08x, limit: 0x%08x%08x\n",
+ regs[o2i(PPB_PREFMEM_BASE_UPPER_REG)], base,
+ regs[o2i(PPB_PREFMEM_LIMIT_UPPER_REG)], limit);
+ } else {
+ base = (base << 16) | 0x00000;
+ limit = (limit << 16) | 0xfffff;
+ printf(" base: 0x%08x, limit: 0x%08x\n", base, limit);
+ }
+ }
+
+ if (regs[o2i(PPB_MAPREG_ROM)] != 0)
+ printf(" Expansion ROM Base Address: 0x%08x\n",
+ regs[o2i(PPB_MAPREG_ROM)]);
+ break;
+
+ default:
+ break;
+ }
+}
+
diff --git a/cfe/cfe/pci/pciconf.c b/cfe/cfe/pci/pciconf.c
new file mode 100644
index 0000000..9f23f7c
--- /dev/null
+++ b/cfe/cfe/pci/pciconf.c
@@ -0,0 +1,1296 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * PCI Configuration File: pciconf.c
+ *
+ *********************************************************************
+ *
+ * Copyright 2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Based in part on the algor p5064 version of pciconf.c:
+ * generic PCI bus configuration
+ * Copyright (c) 1999 Algorithmics Ltd
+ * which in turn appears to be based on PMON code.
+ */
+
+#include "cfe_pci.h"
+#include "cfe_timer.h"
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+#include "lib_malloc.h"
+
+#include "pcivar.h"
+#include "pcireg.h"
+#include "pcidevs.h"
+#include "ldtreg.h"
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+#define PRINTF printf
+#define VPRINTF vprintf
+
+extern void cfe_ledstr(const char *);
+#define SBD_DISPLAY(msg) cfe_ledstr(msg)
+
+int _pciverbose;
+
+/* pci_devinfo uses sprintf(), and we don't necessarily want to drag
+ in all those tables for a minimal build, so set this function
+ pointer if it is required. */
+void (*_pci_devinfo_func) (pcireg_t, pcireg_t, int, char *);
+
+int _pci_nbus; /* start off with one bus */
+const int _pci_maxbus; /* maximum number of busses */
+int _pci_enumerated = 0;
+
+/* The "devices" here are actually PCI "functions" */
+#ifndef PCIMAX_DEV
+#define PCIMAX_DEV 16 /* arbitrary */
+#endif
+#ifndef PCIMAX_MEMWIN
+#define PCIMAX_MEMWIN 3 /* arbitrary per device */
+#endif
+#ifndef PCIMAX_IOWIN
+#define PCIMAX_IOWIN 1 /* arbitrary per device */
+#endif
+
+struct pcidev {
+ struct pci_attach_args *pa;
+ int bus;
+ unsigned char min_gnt;
+ unsigned char max_lat;
+ short nmemwin;
+ short niowin;
+};
+
+struct pciwin {
+ struct pcidev *dev;
+ int reg;
+ size_t size;
+ pcireg_t address;
+};
+
+struct pcirange {
+ pcireg_t base;
+ pcireg_t next;
+ pcireg_t limit;
+};
+
+static struct pci_attach_args *pciarg; /* the array of devices (external) */
+static struct pcidev *pcidev; /* parallel attr array (internal) */
+static int pcindev;
+static int pcimaxdev;
+
+static struct pciwin *pcimemwin; /* the array of memory windows */
+static int pcinmemwin;
+static int pcimaxmemwin;
+static struct pcirange pcimemaddr;
+
+static struct pciwin *pciiowin; /* the array of i/o windows */
+static int pciniowin;
+static int pcimaxiowin;
+static struct pcirange pciioaddr;
+
+
+/* The pass 1 SB-1250 LDT host bridge (LHB) does not implement the base
+ and limit registers for its secondary bus correctly. To compensate,
+ the following code includes hardware-dependent extensions to:
+ - pad the assignment of addresses on the "first" bus behind that
+ bridge (its secondary) so that the 32 bytes starting at the base
+ address are unused.
+ - pad the assignment of addresses on the "first" bus not behind that
+ bridge (the successor to its subordinate bus) so that the 32 bytes
+ starting at the limit address + 1 are unused.
+ - derive values assigned to the mem and io limit registers from
+ the last allocated address + 1, not from the last allocated
+ address as specified for conforming PCI bridges.
+ For pass 1 parts, the revision of the LHB is 1. This problem is fixed
+ and the workaround is unnecessary for revision numbers greater than 1.
+*/
+
+static int lhb_secondary_bus;
+static int lhb_subordinate_bus;
+
+
+static void
+print_bdf (int bus, int device, int function)
+{
+ PRINTF ("PCI");
+ if (bus >= 0)
+ PRINTF (" bus %d", bus);
+ if (device >= 0)
+ PRINTF (" slot %d", device);
+ if (function >= 0)
+ PRINTF ("/%d", function);
+ PRINTF (": ");
+}
+
+void
+pci_bdfprintf (int bus, int device, int function, const char *fmt, ...)
+{
+ va_list arg;
+
+ print_bdf (bus, device, function);
+#ifdef __VARARGS_H
+ va_start(arg);
+#else
+ va_start(arg, fmt);
+#endif
+ VPRINTF (fmt, arg);
+ va_end(arg);
+}
+
+void
+pci_tagprintf (pcitag_t tag, const char *fmt, ...)
+{
+ va_list arg;
+ int bus, device, function;
+
+ pci_break_tag (tag, &bus, &device, &function);
+ print_bdf (bus, device, function);
+
+#ifdef __VARARGS_H
+ va_start(arg);
+#else
+ va_start(arg, fmt);
+#endif
+ VPRINTF (fmt, arg);
+ va_end(arg);
+}
+
+
+/* Initialize the pci-pci bridges and bus hierarchy. */
+
+/* let rec */
+static void pci_businit (int bus, pci_flags_t flags);
+
+static void
+pci_businit_dev_func (pcitag_t tag, pci_flags_t flags)
+{
+ pcireg_t id, class, bhlc;
+
+ class = pci_conf_read(tag, PCI_CLASS_REG);
+ id = pci_conf_read(tag, PCI_ID_REG);
+ bhlc = pci_conf_read(tag, PCI_BHLC_REG);
+
+ pcindev++;
+
+ if (PCI_CLASS(class) == PCI_CLASS_BRIDGE && PCI_HDRTYPE_TYPE(bhlc) == 1) {
+ enum {NONE, PCI, LDT} sec_type;
+ int offset;
+ int bus, device, function;
+ int bus2;
+ struct pci_bus *psec;
+ pcireg_t data;
+
+ sec_type = NONE;
+ offset = 0;
+ switch (PCI_SUBCLASS(class)) {
+ case PCI_SUBCLASS_BRIDGE_PCI:
+ /* See if there is an LDT capability for the secondary. */
+ offset = pci_find_ldt_cap(tag, LDT_SECONDARY);
+ sec_type = offset == 0 ? PCI : LDT;
+ break;
+ case PCI_SUBCLASS_BRIDGE_HOST:
+ case PCI_SUBCLASS_BRIDGE_MISC:
+ /* A Type 1 host bridge (e.g., SB-1250 LDT) or an
+ X-to-LDT bridge with unassigned subclass (LDT?).
+ Probe iff the secondary is LDT (best policy?) */
+ offset = pci_find_ldt_cap(tag, LDT_SECONDARY);
+ if (offset != 0) sec_type = LDT;
+ break;
+ }
+
+ if (sec_type == NONE || _pci_nbus == _pci_maxbus)
+ return;
+
+ pci_break_tag(tag, &bus, &device, &function);
+
+ if (sec_type == LDT && offset != 0) {
+ pcireg_t cr = pci_conf_read(tag, offset+LDT_COMMAND_CAP_OFF);
+ if ((cr & LDT_COMMAND_DOUBLE_ENDED) != 0)
+ return;
+ }
+
+ bus2 = _pci_nbus;
+ psec = &_pci_bus[_pci_nbus];
+ _pci_nbus++;
+
+ psec->tag = tag;
+ psec->primary = bus;
+
+ /*
+ * set primary to bus
+ * set secondary to _pci_nbus
+ * set subordinate to max possible bus number
+ */
+ data = (PCI_BUSMAX << 16) | (bus2 << 8) | bus;
+ pci_conf_write(tag, PPB_BUSINFO_REG, data);
+
+ /*
+ * set base interrupt mapping.
+ */
+ if (bus == 0) {
+ /* We assume board-specific wiring for bus 0 devices. */
+ psec->inta_shift = pci_int_shift_0(tag);
+ } else {
+ /* We assume expansion boards wired per PCI Bridge spec */
+ psec->inta_shift = (_pci_bus[bus].inta_shift + device) % 4;
+ }
+
+ /* if the new bus is LDT, do the fabric initialization */
+ if (sec_type == LDT)
+ _pci_bus[bus2].no_probe = ldt_chain_init(tag, bus2, flags);
+ else
+ _pci_bus[bus2].no_probe = 0;
+
+#ifdef _CSWARM_
+ /* We must avoid attempting to scan the secondary bus of the
+ diagnostic sturgeon on a cswarm (MasterAbortMode == 0
+ appears not to suppress propagation of aborts). We know
+ its secondary bus number will be 2 on cswarm. */
+ if (bus2 == 2)
+ _pci_bus[bus2].no_probe = 1;
+#endif
+
+ /* Scan the new bus for PCI-PCI bridges and initialize. To
+ avoid a chip erratum, we must skip this for double-hosted
+ chains with no secondary devices. The no_probe attribute
+ is a workaround (see ldt_chain_init above). */
+ if (_pci_bus[bus2].no_probe) {
+ _pci_bus[bus2].min_io_addr = 0xffffffff;
+ _pci_bus[bus2].max_io_addr = 0;
+ _pci_bus[bus2].min_mem_addr = 0xffffffff;
+ _pci_bus[bus2].max_mem_addr = 0;
+ } else
+ pci_businit(bus2, flags);
+
+ /* reset subordinate bus number */
+ data = (data & 0xff00ffff) | ((_pci_nbus - 1) << 16);
+ pci_conf_write(tag, PPB_BUSINFO_REG, data);
+
+ /* SB-1250 pass 1 work-around: remember the buses behind the
+ LDT host bridge. This is not the far end of a
+ double-hosted chain. */
+ if (PCI_VENDOR(id) == PCI_VENDOR_SIBYTE &&
+ PCI_PRODUCT(id) == PCI_PRODUCT_SIBYTE_SB1250_LDT &&
+ PCI_REVISION(class) == 1) {
+ lhb_secondary_bus = bus2;
+ lhb_subordinate_bus = _pci_nbus - 1;
+ }
+ }
+}
+
+static void
+pci_businit_dev (int bus, int device, pci_flags_t flags)
+{
+ pcitag_t tag;
+ pcireg_t bhlc;
+ int function, maxfunc;
+
+ tag = pci_make_tag(bus, device, 0);
+ if (!pci_canscan (tag))
+ return;
+
+ if (!pci_probe_tag(tag))
+ return;
+
+ bhlc = pci_conf_read(tag, PCI_BHLC_REG);
+ maxfunc = PCI_HDRTYPE_MULTIFN(bhlc) ? PCI_FUNCMAX : 0;
+
+ for (function = 0; function <= maxfunc; function++) {
+ tag = pci_make_tag(bus, device, function);
+ if (pci_probe_tag(tag))
+ pci_businit_dev_func(tag, flags);
+ }
+}
+
+
+static void
+pci_businit (int bus, pci_flags_t flags)
+{
+ struct pci_bus *ppri;
+ int device;
+
+ ppri = &_pci_bus[bus];
+ ppri->min_io_addr = 0xffffffff;
+ ppri->max_io_addr = 0;
+ ppri->min_mem_addr = 0xffffffff;
+ ppri->max_mem_addr = 0;
+
+ /* Pass 1 errata: we must number the buses in ascending order to
+ avoid problems with the LDT host bridge capturing all
+ configuration cycles. */
+
+ for (device = 0; device <= PCI_DEVMAX; device++)
+ pci_businit_dev (bus, device, flags);
+}
+
+
+/* Scan each PCI device on the system and record its configuration
+ requirements. */
+
+static void
+pci_query_dev_func (pcitag_t tag)
+{
+ pcireg_t id, class;
+ pcireg_t old, mask;
+ pcireg_t stat;
+ pcireg_t bparam;
+ pcireg_t icr;
+ pcireg_t bhlc;
+ pcireg_t t; /* used for pushing writes to cfg registers */
+ unsigned int x;
+ int reg, mapreg_end, mapreg_rom;
+ struct pci_bus *pb;
+ struct pci_attach_args *pa;
+ struct pcidev *pd;
+ struct pciwin *pm, *pi;
+ int bus, device, function, incr;
+ uint16_t cmd;
+ uint8_t pin, pci_int;
+
+ class = pci_conf_read(tag, PCI_CLASS_REG);
+ id = pci_conf_read(tag, PCI_ID_REG);
+ pci_break_tag(tag, &bus, &device, &function);
+
+ if (_pciverbose && _pci_devinfo_func) {
+ char devinfo[256];
+ (*_pci_devinfo_func)(id, class, 1, devinfo);
+ pci_tagprintf(tag, "%s\n", devinfo);
+ }
+
+ if (pcindev >= pcimaxdev) {
+ panic ("pci: unexpected device number\n");
+ return;
+ }
+
+ pa = &pciarg[pcindev];
+ pa->pa_tag = tag;
+ pa->pa_id = id;
+ pa->pa_class = class;
+
+ pd = &pcidev[pcindev++];
+ pd->pa = pa;
+ pd->bus = bus;
+ pd->nmemwin = 0;
+ pd->niowin = 0;
+
+ pb = &_pci_bus[bus];
+ pb->ndev++;
+
+ stat = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
+
+ /* do all devices support fast back-to-back */
+ if ((stat & PCI_STATUS_BACKTOBACK_SUPPORT) == 0)
+ pb->fast_b2b = 0; /* no, sorry */
+
+ /* do all devices run at 66 MHz */
+ if ((stat & PCI_STATUS_66MHZ_SUPPORT) == 0)
+ pb->freq66 = 0; /* no, sorry */
+
+ /* find slowest devsel */
+ x = PCI_STATUS_DEVSEL(stat);
+ if (x > pb->devsel)
+ pb->devsel = x;
+
+ bparam = pci_conf_read(tag, PCI_BPARAM_INTERRUPT_REG);
+
+ pd->min_gnt = PCI_BPARAM_GRANT (bparam);
+ pd->max_lat = PCI_BPARAM_LATENCY (bparam);
+
+ if (pd->min_gnt != 0 || pd->max_lat != 0) {
+ /* find largest minimum grant time of all devices */
+ if (pd->min_gnt != 0 && pd->min_gnt > pb->min_gnt)
+ pb->min_gnt = pd->min_gnt;
+
+ /* find smallest maximum latency time of all devices */
+ if (pd->max_lat != 0 && pd->max_lat < pb->max_lat)
+ pb->max_lat = pd->max_lat;
+
+ if (pd->max_lat != 0)
+ /* subtract our minimum on-bus time per sec from bus bandwidth */
+ pb->bandwidth -= pd->min_gnt * 4000000 /
+ (pd->min_gnt + pd->max_lat);
+ }
+
+ /* Hook any special setup code and test for skipping resource
+ allocation, e.g., for our own host bridges. */
+ if (pci_device_preset(tag) != 0)
+ return;
+
+ /* Does the function need an interrupt mapping? */
+ icr = pci_conf_read(tag, PCI_BPARAM_INTERRUPT_REG);
+ pin = PCI_INTERRUPT_PIN(icr);
+ icr &=~ (PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
+ if (pin == PCI_INTERRUPT_PIN_NONE)
+ pci_int = 0;
+ else if (bus == 0)
+ pci_int = pci_int_map_0(tag);
+ else
+ pci_int = (pb->inta_shift + device + (pin - 1)) % 4 + 1;
+ icr |= pci_int_line(pci_int) << PCI_INTERRUPT_LINE_SHIFT;
+ pci_conf_write(tag, PCI_BPARAM_INTERRUPT_REG, icr);
+
+ /* Find and size the BARs */
+ bhlc = pci_conf_read(tag, PCI_BHLC_REG);
+ switch (PCI_HDRTYPE_TYPE(bhlc)) {
+ case 0: /* Type 0 */
+ mapreg_end = PCI_MAPREG_END;
+ mapreg_rom = PCI_MAPREG_ROM;
+ break;
+ case 1: /* Type 1 (bridge) */
+ mapreg_end = PCI_MAPREG_PPB_END;
+ mapreg_rom = PCI_MAPREG_PPB_ROM;
+ break;
+ case 2: /* Type 2 (cardbus) */
+ mapreg_end = PCI_MAPREG_PCB_END;
+ mapreg_rom = PCI_MAPREG_NONE;
+ break;
+ default: /* unknown */
+ mapreg_end = PCI_MAPREG_START; /* assume none */
+ mapreg_rom = PCI_MAPREG_NONE;
+ break;
+ }
+
+ cmd = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
+ cmd &= (PCI_COMMAND_MASK << PCI_COMMAND_SHIFT); /* don't clear status */
+ pci_conf_write(tag, PCI_COMMAND_STATUS_REG,
+ cmd & ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE));
+ t = pci_conf_read(tag, PCI_COMMAND_STATUS_REG); /* push the write */
+
+ for (reg = PCI_MAPREG_START; reg < mapreg_end; reg += incr) {
+ old = pci_conf_read(tag, reg);
+ pci_conf_write(tag, reg, 0xffffffff);
+ mask = pci_conf_read(tag, reg);
+ pci_conf_write(tag, reg, old);
+
+ /* Assume 4 byte reg, unless we find out otherwise below. */
+ incr = 4;
+
+ /* 0 if not implemented, all-1s if (for some reason) 2nd half
+ of 64-bit BAR or if device broken and reg not implemented
+ (should return 0). */
+ if (mask == 0 || mask == 0xffffffff)
+ continue;
+
+ if (_pciverbose >= 3)
+ pci_tagprintf (tag, "reg 0x%x = 0x%x\n", reg, mask);
+
+ if (PCI_MAPREG_TYPE(mask) == PCI_MAPREG_TYPE_IO) {
+
+ mask |= 0xffff0000; /* must be ones */
+
+ if (pciniowin >= pcimaxiowin) {
+ PRINTF ("pci: too many i/o windows\n");
+ continue;
+ }
+ pi = &pciiowin[pciniowin++];
+
+ pi->dev = pd;
+ pi->reg = reg;
+ pi->size = -(PCI_MAPREG_IO_ADDR(mask));
+ pd->niowin++;
+ } else {
+ switch (PCI_MAPREG_MEM_TYPE(mask)) {
+ case PCI_MAPREG_MEM_TYPE_32BIT:
+ case PCI_MAPREG_MEM_TYPE_32BIT_1M:
+ break;
+ case PCI_MAPREG_MEM_TYPE_64BIT:
+ incr = 8;
+ {
+ pcireg_t oldhi, maskhi;
+
+ if (reg + 4 >= PCI_MAPREG_END) {
+ pci_tagprintf (tag,
+ "misplaced 64-bit region ignored\n");
+ continue;
+ }
+
+ oldhi = pci_conf_read(tag, reg + 4);
+ pci_conf_write(tag, reg + 4, 0xffffffff);
+ maskhi = pci_conf_read(tag, reg + 4);
+ pci_conf_write(tag, reg + 4, oldhi);
+
+ if (maskhi != 0xffffffff) {
+ pci_tagprintf (tag,
+ "true 64-bit region (%08x) ignored\n",
+ maskhi);
+ continue;
+ }
+ }
+ break;
+ default:
+ pci_tagprintf (tag, "reserved mapping type 0x%x\n",
+ PCI_MAPREG_MEM_TYPE(mask));
+ continue;
+ }
+
+ if (!PCI_MAPREG_MEM_PREFETCHABLE(mask))
+ _pci_bus[bus].prefetch = 0;
+
+ if (pcinmemwin >= pcimaxmemwin) {
+ PRINTF ("pci: too many memory windows\n");
+ continue;
+ }
+ pm = &pcimemwin[pcinmemwin++];
+
+ pm->dev = pd;
+ pm->reg = reg;
+ pm->size = -(PCI_MAPREG_MEM_ADDR(mask));
+ pd->nmemwin++;
+ }
+ }
+
+ /* Finally check for Expansion ROM */
+ if (mapreg_rom != PCI_MAPREG_NONE) {
+ reg = mapreg_rom;
+ old = pci_conf_read(tag, reg);
+ pci_conf_write(tag, reg, 0xfffffffe);
+ mask = pci_conf_read(tag, reg);
+ pci_conf_write(tag, reg, old);
+
+ /* 0 if not implemented, 0xfffffffe or 0xffffffff if device
+ broken and/or register not implemented. */
+ if (mask != 0 && mask != 0xfffffffe && mask != 0xffffffff) {
+ if (_pciverbose >= 3)
+ pci_tagprintf (tag, "reg 0x%x = 0x%x\n", reg, mask);
+
+ if (pcinmemwin >= pcimaxmemwin) {
+ PRINTF ("pci: too many memory windows\n");
+ goto done;
+ }
+
+ pm = &pcimemwin[pcinmemwin++];
+ pm->dev = pd;
+ pm->reg = reg;
+ pm->size = -(PCI_MAPREG_ROM_ADDR(mask));
+ pd->nmemwin++;
+ }
+ }
+
+done:
+ cmd |= PCI_COMMAND_INVALIDATE_ENABLE; /* any reason not to? */
+ pci_conf_write(tag, PCI_COMMAND_STATUS_REG, cmd);
+}
+
+static void
+pci_query_dev (int bus, int device)
+{
+ pcitag_t tag;
+ pcireg_t bhlc;
+ int probed, function, maxfunc;
+
+ tag = pci_make_tag(bus, device, 0);
+ if (!pci_canscan (tag))
+ return;
+
+ if (_pciverbose >= 2)
+ pci_bdfprintf (bus, device, -1, "probe...");
+
+ probed = pci_probe_tag(tag);
+
+ if (_pciverbose >= 2)
+ PRINTF ("completed\n");
+
+ if (!probed)
+ return;
+
+ bhlc = pci_conf_read(tag, PCI_BHLC_REG);
+ maxfunc = PCI_HDRTYPE_MULTIFN(bhlc) ? PCI_FUNCMAX : 0;
+
+ for (function = 0; function <= maxfunc; function++) {
+ tag = pci_make_tag(bus, device, function);
+ if (pci_probe_tag(tag))
+ pci_query_dev_func(tag);
+ }
+
+ if (_pciverbose >= 2)
+ pci_bdfprintf (bus, device, -1, "done\n");
+}
+
+
+static void
+pci_query (int bus)
+{
+ int device;
+ struct pci_bus *pb = &_pci_bus[bus];
+ pcireg_t sec_status;
+ unsigned int def_ltim, max_ltim;
+
+ if (bus != 0) {
+ sec_status = pci_conf_read(pb->tag, PPB_IO_STATUS_REG);
+ pb->fast_b2b = (sec_status & PCI_STATUS_BACKTOBACK_SUPPORT) ? 1 : 0;
+ pb->freq66 = (sec_status & PCI_STATUS_66MHZ_SUPPORT) ? 1 : 0;
+ }
+
+ if (pb->no_probe)
+ pb->ndev = 0;
+ else {
+ for (device = 0; device <= PCI_DEVMAX; device++)
+ pci_query_dev (bus, device);
+ }
+
+ if (pb->ndev != 0) {
+ /* convert largest minimum grant time to cycle count */
+ max_ltim = pb->min_gnt * (pb->freq66 ? 66 : 33) / 4;
+
+ /* now see how much bandwidth is left to distribute */
+ if (pb->bandwidth <= 0) {
+ pci_bdfprintf (bus, -1, -1, "warning: total bandwidth exceeded\n");
+ def_ltim = 1;
+ } else {
+ /* calculate a fair share for each device */
+ def_ltim = pb->bandwidth / pb->ndev;
+ if (def_ltim > pb->max_lat)
+ /* that would exceed critical time for some device */
+ def_ltim = pb->max_lat;
+ /* convert to cycle count */
+ def_ltim = def_ltim * (pb->freq66 ? 66 : 33) / 4;
+ }
+ /* most devices don't implement bottom three bits, so round up */
+ def_ltim = (def_ltim + 7) & ~7;
+ max_ltim = (max_ltim + 7) & ~7;
+
+ pb->def_ltim = MIN (def_ltim, 255);
+ pb->max_ltim = MIN (MAX (max_ltim, def_ltim), 255);
+ }
+}
+
+
+static int
+wincompare (const void *a, const void *b)
+{
+ const struct pciwin *wa = a, *wb = b;
+ if (wa->dev->bus != wb->dev->bus)
+ /* sort into ascending order of bus number */
+ return (int)(wa->dev->bus - wb->dev->bus);
+ else
+ /* sort into descending order of size */
+ return (int)(wb->size - wa->size);
+}
+
+
+static pcireg_t
+pci_allocate_io(pcitag_t tag, size_t size)
+{
+ pcireg_t address;
+
+ /* allocate upwards after rounding to size boundary */
+ address = (pciioaddr.next + (size - 1)) & ~(size - 1);
+ if (address < pciioaddr.next || address + size > pciioaddr.limit)
+ return -1;
+ pciioaddr.next = address + size;
+ return address;
+}
+
+static pcireg_t
+pci_align_io_addr(pcireg_t addr)
+{
+ /* align to appropriate bridge boundaries (4K for Rev 1.1 Bridge Arch).
+ Over/underflow will show up in subsequent allocations. */
+ return (addr + ((1 << 12)-1)) & ~((1 << 12)-1);
+}
+
+static void
+pci_assign_iowins(int bus, struct pciwin *pi_first, struct pciwin *pi_limit)
+{
+ struct pciwin *pi;
+ struct pci_bus *pb = &_pci_bus[bus];
+ pcireg_t t; /* for pushing writes */
+
+ pciioaddr.next = pci_align_io_addr(pciioaddr.next);
+
+ /* Pass 1 errata work around. Avoid assigning any real devices
+ at the base address of the LDT host bridge. */
+ if (bus == lhb_secondary_bus) {
+ pb->min_io_addr = pciioaddr.next;
+ pciioaddr.next += (1 << 12);
+ pb->max_io_addr = pciioaddr.next - 1;
+ }
+
+ for (pi = pi_first; pi < pi_limit; pi++) {
+ struct pcidev *pd = pi->dev;
+ pcitag_t tag = pd->pa->pa_tag;
+ pcireg_t base;
+
+ if (pd->niowin < 0)
+ continue;
+ pi->address = pci_allocate_io (tag, pi->size);
+ if (pi->address == -1) {
+ pci_tagprintf (tag,
+ "not enough PCI i/o space (%ld requested)\n",
+ (long)pi->size);
+ pd->nmemwin = pd->niowin = -1;
+ continue;
+ }
+
+ if (pi->address < pb->min_io_addr)
+ pb->min_io_addr = pi->address;
+ if (pi->address + pi->size - 1 > pb->max_io_addr)
+ pb->max_io_addr = pi->address + pi->size - 1;
+
+ if (_pciverbose >= 2)
+ pci_tagprintf (tag,
+ "I/O BAR at 0x%x gets %ld bytes @ 0x%x\n",
+ pi->reg, (long)pi->size, pi->address);
+ base = pci_conf_read(tag, pi->reg);
+ base = (base & ~PCI_MAPREG_IO_ADDR_MASK) | pi->address;
+ pci_conf_write(tag, pi->reg, base);
+ t = pci_conf_read(tag, pi->reg);
+ }
+
+ if (pb->min_io_addr < pb->max_io_addr) {
+ /* if any io on bus, expand to valid bridge limit */
+ pb->max_io_addr |= ((1 << 12)-1);
+ pciioaddr.next = pb->max_io_addr + 1;
+ }
+
+ /* More Pass 1 errata work around. Make sure the 32 bytes beyond
+ the LDT window are not allocated by reserving an entire quantum
+ of io space. */
+ if (bus == lhb_subordinate_bus) {
+ pciioaddr.next = pci_align_io_addr(pciioaddr.next) + (1 << 12);
+ }
+}
+
+static void
+pci_setup_iowins (void)
+{
+ struct pciwin *pi, *pi_first, *pi_limit;
+ int bus;
+
+ qsort(pciiowin, pciniowin, sizeof(struct pciwin), wincompare);
+ pi_first = pciiowin;
+ pi_limit = &pciiowin[pciniowin];
+
+ for (bus = 0; bus < _pci_nbus; bus++) {
+ pi = pi_first;
+ while (pi != pi_limit && pi->dev->bus == bus)
+ pi++;
+ pci_assign_iowins(bus, pi_first, pi);
+ pi_first = pi;
+ }
+}
+
+
+static pcireg_t
+pci_allocate_mem(pcitag_t tag, size_t size)
+{
+ pcireg_t address;
+
+ /* allocate upwards after rounding to size boundary */
+ address = (pcimemaddr.next + (size - 1)) & ~(size - 1);
+ if (address < pcimemaddr.next || address + size > pcimemaddr.limit)
+ return -1;
+ pcimemaddr.next = address + size;
+ return address;
+}
+
+static pcireg_t
+pci_align_mem_addr(pcireg_t addr)
+{
+ /* align to appropriate bridge boundaries (1M for Rev 1.1 Bridge Arch).
+ Over/underflow will show up in subsequent allocations. */
+ return (addr + ((1 << 20)-1)) & ~((1 << 20)-1);
+}
+
+static void
+pci_assign_memwins(int bus, struct pciwin *pm_first, struct pciwin *pm_limit)
+{
+ struct pciwin *pm;
+ struct pci_bus *pb = &_pci_bus[bus];
+ pcireg_t t; /* for pushing writes */
+
+ pcimemaddr.next = pci_align_mem_addr(pcimemaddr.next);
+
+ /* Pass 1 errata work around. Avoid assigning any real devices
+ at the base address of the LDT host bridge. */
+ if (bus == lhb_secondary_bus) {
+ pb->min_mem_addr = pcimemaddr.next;
+ pcimemaddr.next += (1 << 20);
+ pb->max_mem_addr = pcimemaddr.next - 1;
+ }
+
+ for (pm = pm_first; pm < pm_limit; ++pm) {
+ struct pcidev *pd = pm->dev;
+ pcitag_t tag = pd->pa->pa_tag;
+
+ if (pd->nmemwin < 0)
+ continue;
+ pm->address = pci_allocate_mem (tag, pm->size);
+ if (pm->address == -1) {
+ pci_tagprintf (tag,
+ "not enough PCI mem space (%ld requested)\n",
+ (long)pm->size);
+ pd->nmemwin = pd->niowin = -1;
+ continue;
+ }
+ if (_pciverbose >= 2)
+ pci_tagprintf (tag,
+ "%s BAR at 0x%x gets %ld bytes @ 0x%x\n",
+ pm->reg != PCI_MAPREG_ROM ? "MEM" : "ROM",
+ pm->reg, (long)pm->size, pm->address);
+
+ if (pm->address < pb->min_mem_addr)
+ pb->min_mem_addr = pm->address;
+ if (pm->address + pm->size - 1 > pb->max_mem_addr)
+ pb->max_mem_addr = pm->address + pm->size - 1;
+
+ if (pm->reg != PCI_MAPREG_ROM) {
+ /* normal memory - expansion rom done below */
+ pcireg_t base = pci_conf_read(tag, pm->reg);
+ base = pm->address | (base & ~PCI_MAPREG_MEM_ADDR_MASK);
+ pci_conf_write(tag, pm->reg, base);
+ t = pci_conf_read(tag, pm->reg);
+ if (PCI_MAPREG_MEM_TYPE(t) == PCI_MAPREG_MEM_TYPE_64BIT) {
+ pci_conf_write(tag, pm->reg + 4, 0);
+ t = pci_conf_read(tag, pm->reg + 4);
+ }
+ }
+ }
+
+ /* align final bus window */
+ if (pb->min_mem_addr < pb->max_mem_addr) {
+ pb->max_mem_addr |= ((1 << 20) - 1);
+ pcimemaddr.next = pb->max_mem_addr + 1;
+ }
+
+ /* More pass 1 errata work around. Make sure the next 32 bytes
+ beyond the LDT window are not used by reserving an entire
+ quantum of PCI memory space. */
+ if (bus == lhb_subordinate_bus) {
+ pcimemaddr.next = pci_align_mem_addr(pcimemaddr.next) + (1 << 20);
+ }
+}
+
+static void
+pci_setup_memwins (void)
+{
+ struct pciwin *pm, *pm_first, *pm_limit;
+ int bus;
+
+ qsort(pcimemwin, pcinmemwin, sizeof(struct pciwin), wincompare);
+ pm_first = pcimemwin;
+ pm_limit = &pcimemwin[pcinmemwin];
+
+ for (bus = 0; bus < _pci_nbus; bus++) {
+ pm = pm_first;
+ while (pm != pm_limit && pm->dev->bus == bus)
+ pm++;
+ pci_assign_memwins(bus, pm_first, pm);
+ pm_first = pm;
+ }
+
+ /* Program expansion rom address base after normal memory base,
+ to keep DEC ethernet chip happy */
+ for (pm = pcimemwin; pm < pm_limit; pm++) {
+ if (pm->reg == PCI_MAPREG_ROM && pm->address != -1) {
+ struct pcidev *pd = pm->dev; /* expansion rom */
+ pcitag_t tag = pd->pa->pa_tag;
+ pcireg_t base;
+ pcireg_t t; /* for pushing writes */
+
+ /* Do not enable ROM at this time -- PCI spec 2.2 s6.2.5.2 last
+ paragraph, says that if the expansion ROM is enabled, accesses
+ to other registers via the BARs may not be done by portable
+ software!!! */
+ base = pci_conf_read(tag, pm->reg);
+ base = pm->address | (base & ~PCI_MAPREG_ROM_ADDR_MASK);
+ base &= ~PCI_MAPREG_ROM_ENABLE;
+ pci_conf_write(tag, pm->reg, base);
+ t = pci_conf_read(tag, pm->reg);
+ }
+ }
+}
+
+
+static void
+pci_setup_ppb(pci_flags_t flags)
+{
+ int i;
+
+ for (i = _pci_nbus - 1; i > 0; i--) {
+ struct pci_bus *psec = &_pci_bus[i];
+ struct pci_bus *ppri = &_pci_bus[psec->primary];
+ if (ppri->min_io_addr > psec->min_io_addr)
+ ppri->min_io_addr = psec->min_io_addr;
+ if (ppri->max_io_addr < psec->max_io_addr)
+ ppri->max_io_addr = psec->max_io_addr;
+ if (ppri->min_mem_addr > psec->min_mem_addr)
+ ppri->min_mem_addr = psec->min_mem_addr;
+ if (ppri->max_mem_addr < psec->max_mem_addr)
+ ppri->max_mem_addr = psec->max_mem_addr;
+ }
+
+ if (_pciverbose >= 2) {
+ struct pci_bus *pb = &_pci_bus[0];
+ if (pb->min_io_addr < pb->max_io_addr)
+ pci_bdfprintf (0, -1, -1, "io 0x%08x-0x%08x\n",
+ pb->min_io_addr, pb->max_io_addr);
+ if (pb->min_mem_addr < pb->max_mem_addr)
+ pci_bdfprintf (0, -1, -1, "mem 0x%08x-0x%08x\n",
+ pb->min_mem_addr, pb->max_mem_addr);
+ }
+
+ for (i = 1; i < _pci_nbus; i++) {
+ struct pci_bus *pb = &_pci_bus[i];
+ pcireg_t cmd;
+ pcireg_t iodata, memdata;
+ pcireg_t brctl;
+ pcireg_t t; /* for pushing writes */
+
+ cmd = pci_conf_read(pb->tag, PCI_COMMAND_STATUS_REG);
+ if (_pciverbose >= 2)
+ pci_bdfprintf (i, -1, -1, "subordinate to bus %d\n", pb->primary);
+
+ cmd |= PCI_COMMAND_MASTER_ENABLE;
+ if (pb->min_io_addr < pb->max_io_addr) {
+ uint32_t io_limit;
+
+ /* Pass 1 work-round: limits are next free, not last used. */
+ io_limit = pb->max_io_addr;
+ if (i == lhb_secondary_bus)
+ io_limit++;
+
+ cmd |= PCI_COMMAND_IO_ENABLE;
+ if (_pciverbose >= 2)
+ pci_bdfprintf (i, -1, -1, "io 0x%08x-0x%08x\n",
+ pb->min_io_addr, io_limit);
+ iodata = pci_conf_read(pb->tag, PPB_IO_STATUS_REG);
+ if ((iodata & PPB_IO_ADDR_CAP_MASK) == PPB_IO_ADDR_CAP_32) {
+ pcireg_t upperdata;
+
+ upperdata = ((pb->min_io_addr) >> 16) & PPB_IO_UPPER_BASE_MASK;
+ upperdata |= (io_limit & PPB_IO_UPPER_LIMIT_MASK);
+ pci_conf_write(pb->tag, PPB_IO_UPPER_REG, upperdata);
+ }
+ iodata = (iodata & ~PPB_IO_BASE_MASK)
+ | ((pb->min_io_addr >> 8) & 0xf0);
+ iodata = (iodata & ~PPB_IO_LIMIT_MASK)
+ | ((io_limit & PPB_IO_LIMIT_MASK) & 0xf000);
+ } else {
+ /* Force an empty window */
+ iodata = pci_conf_read(pb->tag, PPB_IO_STATUS_REG);
+ iodata &=~ (PPB_IO_BASE_MASK | PPB_IO_LIMIT_MASK);
+ iodata |= (1 << 4) | (0 << (8+4));
+ }
+ pci_conf_write(pb->tag, PPB_IO_STATUS_REG, iodata);
+ /* Push the write (see SB-1250 Errata, Section 8.10) */
+ t = pci_conf_read(pb->tag, PPB_IO_STATUS_REG);
+
+ if (pb->min_mem_addr < pb->max_mem_addr) {
+ uint32_t mem_limit;
+
+ /* SB-1250 pass 1 workaround: limit is next free, not last used */
+ mem_limit = pb->max_mem_addr;
+ if (i == lhb_secondary_bus)
+ mem_limit++;
+
+ cmd |= PCI_COMMAND_MEM_ENABLE;
+ if (_pciverbose >= 2)
+ pci_bdfprintf (i, -1, -1, "mem 0x%08x-0x%08x\n",
+ pb->min_mem_addr, mem_limit);
+ memdata = pci_conf_read(pb->tag, PPB_MEM_REG);
+ memdata = (memdata & ~PPB_MEM_BASE_MASK)
+ | ((pb->min_mem_addr >> 16) & 0xfff0);
+ memdata = (memdata & ~PPB_MEM_LIMIT_MASK)
+ | ((mem_limit & PPB_MEM_LIMIT_MASK) & 0xfff00000);
+ } else {
+ /* Force an empty window */
+ memdata = pci_conf_read(pb->tag, PPB_MEM_REG);
+ memdata &=~ (PPB_MEM_BASE_MASK | PPB_MEM_LIMIT_MASK);
+ memdata |= (1 << 4) | (0 << (16+4));
+ }
+ pci_conf_write(pb->tag, PPB_MEM_REG, memdata);
+ /* Push the write (see SB-1250 Errata, Section 8.10) */
+ t = pci_conf_read(pb->tag, PPB_MEM_REG);
+
+ /* Force an empty prefetchable memory window */
+ memdata = pci_conf_read(pb->tag, PPB_PREFMEM_REG);
+ memdata &=~ (PPB_MEM_BASE_MASK | PPB_MEM_LIMIT_MASK);
+ memdata |= (1 << 4) | (0 << (16+4));
+ pci_conf_write(pb->tag, PPB_PREFMEM_REG, memdata);
+ /* Push the write (see SB-1250 Errata, Section 8.10) */
+ t = pci_conf_read(pb->tag, PPB_PREFMEM_REG);
+
+ /* Do any final bridge dependent initialization */
+ pci_bridge_setup(pb->tag, flags);
+
+ brctl = pci_conf_read(pb->tag, PPB_BRCTL_INTERRUPT_REG);
+#ifdef _SB1250_PASS2_
+ /* LDT MasterAborts _will_ cause bus errors in pass 2 when
+ enabled. Pending negotiations with clients, leave
+ MasterAbortMode off to disable their propagation. */
+#else
+ brctl |= (PPB_BRCTL_SERR_ENABLE | PPB_BRCTL_MASTER_ABORT_MODE);
+#endif
+ if (pb->fast_b2b)
+ brctl |= PPB_BRCTL_BACKTOBACK_ENABLE;
+ pci_conf_write(pb->tag, PPB_BRCTL_INTERRUPT_REG, brctl);
+ t = pci_conf_read(pb->tag, PPB_BRCTL_INTERRUPT_REG); /* push */
+
+ pci_conf_write(pb->tag, PCI_COMMAND_STATUS_REG, cmd);
+ }
+}
+
+
+int
+pci_cacheline_log2 (void)
+{
+ /* default to 8 words == 2^3 */
+ return 3;
+}
+
+
+int
+pci_maxburst_log2 (void)
+{
+ return 32; /* no limit */
+}
+
+static void
+pci_setup_devices (pci_flags_t flags)
+{
+ struct pcidev *pd;
+
+ /* Enable each PCI interface */
+ for (pd = pcidev; pd < &pcidev[pcindev]; pd++) {
+ struct pci_bus *pb = &_pci_bus[pd->bus];
+ pcitag_t tag = pd->pa->pa_tag;
+ pcireg_t cmd, misc;
+ unsigned int ltim;
+
+ /* Consider setting interrupt line here */
+
+ cmd = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
+ cmd |= PCI_COMMAND_MASTER_ENABLE
+ | PCI_COMMAND_SERR_ENABLE
+ | PCI_COMMAND_PARITY_ENABLE;
+ /* Always enable i/o & memory space, in case this card is
+ just snarfing space from the fixed ISA block and doesn't
+ declare separate PCI space. */
+ cmd |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE;
+ if (pb->fast_b2b)
+ cmd |= PCI_COMMAND_BACKTOBACK_ENABLE;
+
+ /* Write status too, to clear any pending error bits. */
+ pci_conf_write(tag, PCI_COMMAND_STATUS_REG, cmd);
+
+ ltim = pd->min_gnt * (pb->freq66 ? 66 : 33) / 4;
+ ltim = MIN (MAX (pb->def_ltim, ltim), pb->max_ltim);
+
+ misc = pci_conf_read (tag, PCI_BHLC_REG);
+ PCI_LATTIMER_SET (misc, ltim);
+ PCI_CACHELINE_SET (misc, 1 << pci_cacheline_log2());
+ pci_conf_write (tag, PCI_BHLC_REG, misc);
+
+ pci_device_setup (tag); /* hook for post setup */
+ }
+}
+
+
+void
+pci_configure (pci_flags_t flags)
+{
+ int bus;
+
+#if (PCI_DEBUG > 1)
+ _pciverbose = 3;
+#else
+ _pciverbose = (flags & PCI_FLG_VERBOSE);
+#endif
+ _pci_devinfo_func = (_pciverbose != 0) ? pci_devinfo : NULL;
+ pciarg = NULL;
+
+ /* SB-1250 pass 1 workaround: discover LHB buses during traversal. */
+ lhb_secondary_bus = lhb_subordinate_bus = -1;
+
+ /* initialise the host bridge(s) */
+ SBD_DISPLAY ("PCIH");
+ if (pci_hwinit(flags) < 0)
+ return;
+
+ /* initialise any PCI-PCI bridges, discover and number buses */
+ SBD_DISPLAY ("PCIB");
+ pcindev = 0;
+ pci_businit(0, flags);
+
+ /* scan configuration space of all devices to collect attributes */
+ SBD_DISPLAY ("PCIS");
+ pcimaxdev = pcindev;
+ pciarg = (struct pci_attach_args *) KMALLOC (pcimaxdev * sizeof(struct pci_attach_args), 0);
+ if (pciarg == NULL) {
+ PRINTF ("pci: no memory for device table\n");
+ pcimaxdev = 0;
+ } else {
+ pcidev = (struct pcidev *) KMALLOC (pcimaxdev * sizeof(struct pcidev), 0);
+ if (pcidev == NULL) {
+ KFREE (pciarg); pciarg = NULL;
+ PRINTF ("pci: no memory for device attribute table\n");
+ pcimaxdev = 0;
+ }
+ }
+ pcindev = 0;
+
+ pcimaxmemwin = PCIMAX_DEV * PCIMAX_MEMWIN;
+ pcimemwin = (struct pciwin *) KMALLOC (pcimaxmemwin * sizeof(struct pciwin), 0);
+ if (pcimemwin == NULL) {
+ PRINTF ("pci: no memory for window table\n");
+ pcimaxmemwin = 0;
+ }
+ pcimaxiowin = PCIMAX_DEV * PCIMAX_IOWIN;
+ pciiowin = (struct pciwin *) KMALLOC (pcimaxiowin * sizeof(struct pciwin), 0);
+ if (pciiowin == NULL) {
+ PRINTF ("pci: no memory for window table\n");
+ pcimaxiowin = 0;
+ }
+
+ pcinmemwin = pciniowin = 0;
+ for (bus = 0; bus < _pci_nbus; bus++) {
+ pci_query (bus);
+ }
+
+ if (pcindev != pcimaxdev) {
+ panic ("Inconsistent device count\n");
+ return;
+ }
+
+ /* alter PCI bridge parameters based on query data */
+ pci_hwreinit (flags);
+
+ /* setup the individual device windows */
+ pcimemaddr.base = minpcimemaddr;
+ pcimemaddr.limit = maxpcimemaddr;
+ pciioaddr.base = minpciioaddr;
+ pciioaddr.limit = maxpciioaddr;
+
+ pcimemaddr.next = pcimemaddr.base;
+ pciioaddr.next = pciioaddr.base;
+ pci_setup_iowins ();
+ pci_setup_memwins ();
+
+ /* set up and enable each device */
+ if (_pci_nbus > 1)
+ pci_setup_ppb (flags);
+ pci_setup_devices (flags);
+
+ KFREE (pciiowin); pciiowin = NULL;
+ KFREE (pcimemwin); pcimemwin = NULL;
+ KFREE (pcidev); pcidev = NULL;
+
+ _pci_enumerated = 1;
+}
+
+
+int
+pci_foreachdev(int (*fn)(pcitag_t tag))
+{
+ int i, rv;
+
+ for (i = 0, rv = 0; i < pcindev && rv == 0; i++)
+ rv = (*fn)(pciarg[i].pa_tag);
+
+ return rv;
+}
+
+
+static int
+dump_configuration(pcitag_t tag)
+{
+ pci_tagprintf(tag, "dump of ");
+ pci_conf_print(tag);
+ return 0;
+}
+
+void
+pci_show_configuration(void)
+{
+ pci_foreachdev(dump_configuration);
+}
+
+int
+pci_find_class(uint32_t class, int enumidx, pcitag_t *tag)
+{
+ int i;
+ struct pci_attach_args *thisdev;
+
+ thisdev = pciarg;
+ for (i = 0; i < pcindev && enumidx >= 0; i++) {
+ if (PCI_CLASS(thisdev->pa_class) == class) {
+ if (enumidx == 0) {
+ *tag = thisdev->pa_tag;
+ return 0;
+ } else {
+ enumidx--;
+ }
+ }
+ thisdev++;
+ }
+
+ return -1;
+}
+
+int
+pci_find_device(uint32_t vid, uint32_t did, int enumidx, pcitag_t *tag)
+{
+ int i;
+ struct pci_attach_args *thisdev;
+
+ thisdev = pciarg;
+ for (i = 0; i < pcindev && enumidx >= 0; i++) {
+ if ((PCI_VENDOR(thisdev->pa_id) == vid) &&
+ (PCI_PRODUCT(thisdev->pa_id) == did)) {
+ if (enumidx == 0) {
+ *tag = thisdev->pa_tag;
+ return 0;
+ } else {
+ enumidx--;
+ }
+ }
+ thisdev++;
+ }
+
+ return -1;
+}
diff --git a/cfe/cfe/pci/pcidevs b/cfe/cfe/pci/pcidevs
new file mode 100644
index 0000000..65b03ab
--- /dev/null
+++ b/cfe/cfe/pci/pcidevs
@@ -0,0 +1,1355 @@
+$pcidevs 2002/09/03 broadcom $
+
+/*
+ * Copyright (c) 1995, 1996 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * NOTE: a fairly complete list of PCI codes can be found at:
+ *
+ * http://members.hyperlink.net.au/~chart/pci.htm
+ *
+ * which replaces the database found at
+ *
+ * http://www.yourvote.com/pci/
+ *
+ * (but it doesn't always seem to match vendor documentation)
+ */
+
+/*
+ * List of known PCI vendors. This list has been trimmed to include
+ * only vendors with products appearing in the lists below.
+ */
+
+vendor COMPAQ 0x0e11 Compaq
+vendor SYMBIOS 0x1000 Symbios Logic
+vendor ATI 0x1002 ATI Technologies
+vendor ULSI 0x1003 ULSI Systems
+vendor VLSI 0x1004 VLSI Technology
+vendor AVANCE 0x1005 Avance Logic
+vendor NS 0x100b National Semiconductor
+vendor TSENG 0x100c Tseng Labs
+vendor WEITEK 0x100e Weitek
+vendor DEC 0x1011 Digital Equipment
+vendor CIRRUS 0x1013 Cirrus Logic
+vendor IBM 0x1014 IBM
+vendor WD 0x101c Western Digital
+vendor AMD 0x1022 Advanced Micro Devices
+vendor TRIDENT 0x1023 Trident Microsystems
+vendor ACER 0x1025 Acer
+vendor MATROX 0x102b Matrox
+vendor CHIPS 0x102c Chips and Technologies
+vendor TOSHIBA 0x102f Toshiba America
+vendor NEC 0x1033 NEC
+vendor FUTUREDOMAIN 0x1036 Future Domain
+vendor SIS 0x1039 Silicon Integrated System
+vendor HP 0x103c Hewlett-Packard
+vendor PCTECH 0x1042 PC Technology
+vendor DPT 0x1044 Distributed Processing Technology
+vendor OPTI 0x1045 Opti
+vendor ELSA 0x1048 Elsa
+vendor SGSTHOMSON 0x104a SGS Thomson Microelectric
+vendor BUSLOGIC 0x104b BusLogic
+vendor TI 0x104c Texas Instruments
+vendor SONY 0x104d Sony
+vendor OAKTECH 0x104e Oak Technology
+vendor WINBOND 0x1050 Winbond Electronics
+vendor MOT 0x1057 Motorola
+vendor PROMISE 0x105a Promise Technology
+vendor NUMBER9 0x105d Number 9 Computer Company
+vendor UMC 0x1060 United Microelectronics
+vendor ITT 0x1061 I. T. T.
+vendor MYLEX 0x1069 Mylex
+vendor APPLE 0x106b Apple Computer
+vendor YAMAHA 0x1073 Yamaha
+vendor NEXGEN 0x1074 NexGen Microsystems
+vendor QLOGIC 0x1077 Q Logic
+vendor LEADTEK 0x107d LeadTek Research
+vendor CONTAQ 0x1080 Contaq Microsystems
+vendor BIT3 0x108a Bit3 Computer Corp.
+vendor OLICOM 0x108d Olicom
+vendor SUN 0x108e Sun Microsystems
+vendor INTERGRAPH 0x1091 Intergraph
+vendor DIAMOND 0x1092 Diamond Computer Systems
+vendor CMDTECH 0x1095 CMD Technology
+vendor QUANTUMDESIGNS 0x1098 Quantum Designs
+vendor BROOKTREE 0x109e Brooktree
+vendor SGI 0x10a9 Silicon Graphics
+vendor ACC 0x10aa ACC Microelectronics
+vendor SYMPHONY 0x10ad Symphony Labs
+vendor PLX 0x10b5 PLX Technology
+vendor MADGE 0x10b6 Madge Networks
+vendor 3COM 0x10B7 3Com
+vendor SMC 0x10b8 Standard Microsystems
+vendor ALI 0x10b9 Acer Labs
+vendor SURECOM 0x10bd Surecom Technology
+vendor SAMSUNGSEMI 0x10c3 Samsung Semiconductors
+vendor NEOMAGIC 0x10c8 Neomagic
+vendor ADVSYS 0x10cd Advanced System Products
+vendor MACRONIX 0x10d9 Macronix
+vendor ES 0x10dd Evans & Sutherland
+vendor NVIDIA 0x10de Nvidia Corporation
+vendor EMULEX 0x10df Emulex
+vendor IMS 0x10e0 Integrated Micro Solutions
+vendor TEKRAM 0x10e1 Tekram Technology (1st PCI Vendor ID)
+vendor NEWBRIDGE 0x10e3 Newbridge Microsystems / Tundra Semiconductor
+vendor AMCIRCUITS 0x10e8 Applied Micro Circuits
+vendor REALTEK 0x10ec Realtek Semiconductor
+vendor NKK 0x10f5 NKK Corporation
+vendor INITIO 0x1101 Initio
+vendor CREATIVELABS 0x1102 Creative Labs
+vendor TRIONES 0x1103 Triones Technologies
+vendor SIGMA 0x1105 Sigma Designs
+vendor VIATECH 0x1106 VIA Technologies
+vendor COGENT 0x1109 Cogent Data Technologies
+vendor RNS 0x1112 RNS
+vendor ACCTON 0x1113 Accton Technology
+vendor VORTEX 0x1119 Vortex Computer Systems
+vendor EFFICIENTNETS 0x111a Efficent Networks
+vendor IDT 0x111d IDT
+vendor FORE 0x1127 FORE Systems
+vendor ZIATECH 0x1138 Ziatech
+vendor ALLIANCE 0x1142 Alliance Semiconductor
+vendor SCHNEIDERKOCH 0x1148 Schneider & Koch
+vendor MUTECH 0x1159 Mutech
+vendor XIRCOM 0x115d Xircom
+vendor ALTERA 0x1172 Altera Corporation
+vendor TOSHIBA2 0x1179 Toshiba America Info Systems
+vendor RICOH 0x1180 Ricoh
+vendor DLINK 0x1186 D-Link Systems
+vendor COROLLARY 0x118c Corrollary
+vendor ACARD 0x1191 Acard
+vendor ZEINET 0x1193 Zeinet
+vendor GALILEO 0x11ab Galileo Technology
+vendor LITEON 0x11ad Lite-On Communications
+vendor V3 0x11b0 V3 Semiconductor
+vendor LUCENT 0x11c1 AT&T Microelectronics
+vendor DOLPHIN 0x11c8 Dolphin Interconnect Solutions
+vendor AURAVISION 0x11d1 Auravision
+vendor ZORAN 0x11de Zoran Corporation
+vendor COMPEX 0x11f6 Compex
+vendor PMCSIERRA 0x11f8 PMC-Sierra
+vendor CYCLADES 0x120e Cyclades
+vendor ESSENTIAL 0x120f Essential Communications
+vendor O2MICRO 0x1217 O2 Micro Inc
+vendor 3DFX 0x121a 3Dfx Interactive
+vendor CCUBE 0x123f C-Cube Microsystems
+vendor AVM 0x1244 AVM
+vendor LINEARSYS 0x1254 Linear Systems
+vendor ASIX 0x125b ASIX Electronics
+vendor ESSTECH 0x125d ESS Technology Inc
+vendor SILMOTION 0x126f Silicon Motion
+vendor ENSONIQ 0x1274 Ensoniq
+vendor DAVICOM 0x1282 Davicom Semiconductor
+vendor ESSTECH2 0x1285 ESS Technology Inc
+vendor TRITECH 0x1292 TriTech Microelectronics
+vendor ALTEON 0x12ae Alteon
+vendor RISCOM 0x12aa RISCom
+vendor USR 0x12b9 US Robotics (3Com)
+vendor NVIDIA_SGS 0x12d2 Nvidia Corporation & SGS Thomson Microelectric
+vendor AUREAL 0x12eb Aureal Semiconductor
+vendor ADMTEK 0x1317 ADMtek
+vendor FORTEMEDIA 0x1319 Forte Media
+vendor DOMEX 0x134a Domex
+vendor LMC 0x1376 LAN Media Corporation
+vendor API 0x14d9 API Networks
+vendor CONEXANT 0x14f1 Conexant Systems
+vendor NETGEAR 0x1385 Netgear
+vendor 3WARE 0x13c1 3ware
+vendor SUNDANCETI 0x13f0 Sundance Technology
+vendor CMEDIA 0x13f6 C-Media Electronics Inc
+vendor DELTA 0x1500 Delta Electronics
+vendor SOLIDUM 0x1588 Solidum Systems Corp.
+vendor SIBYTE 0x166d SiByte, Inc.
+vendor SYMPHONY2 0x1c1c Symphony Labs (2nd PCI Vendor ID)
+vendor TEKRAM2 0x1de1 Tekram Technology (2nd PCI Vendor ID)
+vendor BROADCOM 0x14e4 Broadcom
+vendor 3DLABS 0x3d3d 3D Labs
+vendor AVANCE2 0x4005 Avance Logic (2nd PCI Vendor ID)
+vendor ADDTRON 0x4033 Addtron Technology
+vendor NETVIN 0x4a14 NetVin
+vendor S3 0x5333 S3
+vendor C4T 0x6374 c't Magazin
+vendor INTEL 0x8086 Intel
+vendor PROLAN 0x8c4a ProLAN
+vendor KTI 0x8e2e KTI
+vendor ADP 0x9004 Adaptec
+vendor ADP2 0x9005 Adaptec (2nd PCI Vendor ID)
+vendor ATRONICS 0x907f Atronics
+vendor ARC 0xedd8 ARC Logic
+vendor EPIGRAM 0xfeda Epigram
+vendor INVALID 0xffff INVALID VENDOR ID
+
+/*
+ * List of known products. Grouped by vendor.
+ */
+
+/* 3COM Products */
+product 3COM 3C985 0x0001 3c985 Gigabit Ethernet
+product 3COM 3C590 0x5900 3c590 Ethernet
+product 3COM 3C595TX 0x5950 3c595-TX 10/100 Ethernet
+product 3COM 3C595T4 0x5951 3c595-T4 10/100 Ethernet
+product 3COM 3C595MII 0x5952 3c595-MII 10/100 Ethernet
+product 3COM 3C900TPO 0x9000 3c900-TPO Ethernet
+product 3COM 3C900COMBO 0x9001 3c900-COMBO Ethernet
+product 3COM 3C905TX 0x9050 3c905-TX 10/100 Ethernet
+product 3COM 3C905T4 0x9051 3c905-T4 10/100 Ethernet
+product 3COM 3C900BTPO 0x9004 3c900B-TPO Ethernet
+product 3COM 3C900BCOMBO 0x9005 3c900B-COMBO Ethernet
+product 3COM 3C900BTPC 0x9006 3c900B-TPC Ethernet
+product 3COM 3C905BTX 0x9055 3c905B-TX 10/100 Ethernet
+product 3COM 3C905BT4 0x9056 3c905B-T4 10/100 Ethernet
+product 3COM 3C905BCOMBO 0x9058 3c905B-COMBO 10/100 Ethernet
+product 3COM 3C905BFX 0x905a 3c905B-FX 100 Ethernet
+product 3COM 3C905CTX 0x9200 3c905C-TX 10/100 Ethernet with mngmt
+product 3COM 3C980SRV 0x9800 3c980 Server Adapter 10/100 Ethernet
+product 3COM 3C980CTXM 0x9805 3c980C-TXM 10/100 Ethernet
+product 3COM 3CR990TX97 0x9903 3CR990-TX-97 10/100 Ethernet
+
+/* 3Dfx Interactive producs */
+product 3DFX VOODOO 0x0001 Voodoo
+product 3DFX VOODOO2 0x0002 Voodoo2
+product 3DFX BANSHEE 0x0003 Banshee
+product 3DFX VOODOO3 0x0005 Voodoo3
+
+/* 3D Labs products */
+product 3DLABS 300SX 0x0001 GLINT 300SX
+product 3DLABS 500TX 0x0002 GLINT 500TX
+product 3DLABS DELTA 0x0003 GLINT DELTA
+product 3DLABS PERMEDIA 0x0004 GLINT Permedia
+product 3DLABS 500MX 0x0006 GLINT 500MX
+product 3DLABS PERMEDI2 0x0007 GLINT Permedia 2
+
+/* 3ware products */
+product 3WARE ESCALADE 0x1000 Escalade IDE RAID
+
+/* ACC Products */
+product ACC 2188 0x0000 ACCM 2188 VL-PCI Bridge
+product ACC 2051_HB 0x2051 2051 PCI Single Chip Solution (host bridge)
+product ACC 2051_ISA 0x5842 2051 PCI Single Chip Solution (ISA bridge)
+
+/* Acard products */
+product ACARD AEC6710 0x8002 AEC6710 SCSI
+product ACARD AEC6712UW 0x8010 AEC6712UW SCSI
+product ACARD AEC6712U 0x8020 AEC6712U SCSI
+product ACARD AEC6712S 0x8030 AEC6712S SCSI
+product ACARD AEC6710D 0x8040 AEC6710D SCSI
+product ACARD AEC6715UW 0x8050 AEC6715UW SCSI
+
+/* Accton products */
+product ACCTON MPX5030 0x1211 MPX 5030/5038 Ethernet
+
+/* Acer products */
+product ACER M1435 0x1435 M1435 VL-PCI Bridge
+
+/* Acer Labs products */
+product ALI M1445 0x1445 M1445 VL-PCI Bridge
+product ALI M1449 0x1449 M1449 PCI-ISA Bridge
+product ALI M1451 0x1451 M1451 Host-PCI Bridge
+product ALI M1461 0x1461 M1461 Host-PCI Bridge
+product ALI M1531 0x1531 M1531 Host-PCI Bridge
+product ALI M1541 0x1541 M1541 Host-PCI Bridge
+product ALI M1543 0x1533 M1543 PCI-ISA Bridge
+product ALI M3309 0x3309 M3309 MPEG Decoder
+product ALI M4803 0x5215 M4803
+product ALI M5229 0x5229 M5229 UDMA IDE Controller
+product ALI M5237 0x5237 M5237 USB Host Controller
+product ALI M7101 0x7101 M7101 Power Management Controller
+
+/* Adaptec products */
+product ADP AIC7850 0x5078 AIC-7850
+product ADP AIC7855 0x5578 AIC-7855
+product ADP AIC5900 0x5900 AIC-5900 ATM
+product ADP AIC5905 0x5905 AIC-5905 ATM
+product ADP AIC6915 0x6915 AIC-6915 10/100 Ethernet
+product ADP AIC7860 0x6078 AIC-7860
+product ADP APA1480 0x6075 APA-1480 Ultra
+product ADP 2940AU 0x6178 AHA-2940A Ultra
+product ADP AIC7870 0x7078 AIC-7870
+product ADP 2940 0x7178 AHA-2940
+product ADP 3940 0x7278 AHA-3940
+product ADP 3985 0x7378 AHA-3985
+product ADP 2944 0x7478 AHA-2944
+product ADP AIC7895 0x7895 AIC-7895 Ultra
+product ADP AIC7880 0x8078 AIC-7880 Ultra
+product ADP 2940U 0x8178 AHA-2940 Ultra
+product ADP 3940U 0x8278 AHA-3940 Ultra
+product ADP 389XU 0x8378 AHA-389X Ultra
+product ADP 2944U 0x8478 AHA-2944 Ultra
+product ADP 2940UP 0x8778 AHA-2940 Ultra Pro
+
+product ADP2 2940U2 0x0010 AHA-2940 Ultra2
+product ADP2 2930U2 0x0011 AHA-2930 Ultra2
+product ADP2 AIC7890 0x001f AIC-7890/1
+product ADP2 3950U2B 0x0050 AHA-3950 Ultra2
+product ADP2 3950U2D 0x0051 AHA-3950 Ultra2
+product ADP2 AIC7896 0x005f AIC-7896/7
+
+/* Addtron Products */
+product ADDTRON 8139 0x1360 8139 Ethernet
+
+/* ADMtek products */
+product ADMTEK AL981 0x0981 ADMtek AL981 10/100 Ethernet
+
+/* Advanced System Products */
+product ADVSYS 1200A 0x1100
+product ADVSYS 1200B 0x1200
+product ADVSYS ULTRA 0x1300 ABP-930/40UA
+product ADVSYS WIDE 0x2300 ABP-940UW
+product ADVSYS U2W 0x2500 ASB-3940U2W
+product ADVSYS U3W 0x2700 ASB-3940U3W
+
+/* Alliance products */
+product ALLIANCE AT24 0x6424 AT24
+product ALLIANCE AT25 0x643d AT25
+
+/* Alteon products */
+product ALTEON ACENIC 0x0001 ACEnic Gigabit Ethernet
+
+/* AMD products */
+product AMD PCNET_PCI 0x2000 79c970 PCnet-PCI LANCE Ethernet
+product AMD PCNET_HOME 0x2001 79c978 PCnet-PCI Home
+product AMD PCSCSI_PCI 0x2020 53c974 PCscsi-PCI SCSI
+product AMD PCNETS_PCI 0x2040 79C974 PCnet-PCI Ethernet & SCSI
+product AMD SC751_SC 0x7006 AMD751 System Controller
+product AMD SC751_PPB 0x7007 AMD751 PCI-to-PCI Bridge
+product AMD PBC756_ISA 0x7408 AMD756 PCI-to-ISA Bridge
+product AMD PBC756_IDE 0x7409 AMD756 IDE controller
+product AMD PBC756_PMC 0x740B AMD756 Power Management Controller
+product AMD PBC756_USB 0x740C AMD756 USB Host Controller
+product AMD HT7520 0x7450 (PLX) HT7520 PCIX Tunnel
+product AMD HT7520_PIC 0x7451 (PLX) HT7520 PCIX IOAPIC
+product AMD AMD8151_AGP 0x7454 AMD8151 AGP Device
+product AMD AMD8151 0x7455 AMD8151 HyperTransport-AGP Bridge
+
+/* API Networks products */
+product API STURGEON 0x0010 AP1011 HyperTransport-PCI Bridge
+
+/* Apple products */
+product APPLE BANDIT 0x0001 Bandit Host-PCI Bridge
+product APPLE GC 0x0002 Grand Central I/O Controller
+product APPLE CONTROL 0x0003 Control
+product APPLE PLANB 0x0004 PlanB
+product APPLE OHARE 0x0007 OHare I/O Controller
+product APPLE BANDIT2 0x0008 Bandit Host-PCI Bridge
+product APPLE HEATHROW 0x0010 MAC-IO I/O Controller (Heathrow)
+product APPLE PADDINGTON 0x0017 MAC-IO I/O Controller (Paddington)
+product APPLE KEYLARGO_USB 0x0019 KeyLargo USB Controller
+product APPLE UNINORTH1 0x001e UniNorth Host-PCI Bridge
+product APPLE UNINORTH2 0x001f UniNorth Host-PCI Bridge
+product APPLE UNINORTH_AGP 0x0020 UniNorth AGP Interface
+product APPLE GMAC 0x0021 GMAC Ethernet
+product APPLE KEYLARGO 0x0022 MAC-IO I/O Controller (KeyLargo)
+
+/* ARC Logic products */
+product ARC 1000PV 0xa091 1000PV
+product ARC 2000PV 0xa099 2000PV
+product ARC 2000MT 0xa0a1 2000MT
+
+/* ASIX Electronics products */
+product ASIX AX88140A 0x1400 AX88140A 10/100 Ethernet
+
+/* ATI products */
+product ATI MACH32 0x4158 Mach32
+product ATI MACH64_CT 0x4354 Mach64 CT
+product ATI MACH64_CX 0x4358 Mach64 CX
+product ATI MACH64_ET 0x4554 Mach64 ET
+product ATI MACH64_VT 0x4654 Mach64 VT
+product ATI MACH64_B 0x4750 Mach64 B
+product ATI MACH64_GB 0x4742 Mach64 GB
+product ATI MACH64_GD 0x4744 Mach64 GD
+product ATI MACH64_GI 0x4749 Mach64 GI
+product ATI MACH64_GP 0x4750 Mach64 GP
+product ATI MACH64_GQ 0x4751 Mach64 GQ
+product ATI MACH64_GT 0x4754 Mach64 GT
+product ATI MACH64_GU 0x4755 Mach64 GU
+product ATI MACH64_GV 0x4756 Mach64 GV
+product ATI MACH64_GW 0x4757 Mach64 GW
+product ATI MACH64_GX 0x4758 Mach64 GX
+product ATI MACH64_GZ 0x475a Mach64 GZ
+product ATI MACH64_LB 0x4c42 Mach64 LB
+product ATI MACH64_LD 0x4c44 Mach64 LD
+product ATI MACH64_LG 0x4c47 Mach64 LG
+product ATI MACH64_LI 0x4c49 Mach64 LI
+product ATI MACH64_LM 0x4c4d Mach64 LM
+product ATI MACH64_LP 0x4c50 Mach64 LP
+product ATI MACH64_LR 0x4c52 Mach64 LR
+
+/* Auravision products */
+product AURAVISION VXP524 0x01f7 VxP524 PCI Video Processor
+
+/* Aureal Semiconductor */
+product AUREAL AU8820 0x0001 AU8820 Vortex Digital Audio Processor
+
+/* Applied Micro Circuts products */
+product AMCIRCUITS S5933 0x4750 S5933 PCI Matchmaker
+product AMCIRCUITS LANAI 0x8043 Myrinet LANai Interface
+product AMCIRCUITS S5920 0x5920 S5920 PCI Target
+
+/* Atronics products */
+product ATRONICS IDE_2015PL 0x2015 IDE-2015PL
+
+/* Avance Logic products */
+product AVANCE AVL2301 0x2301 AVL2301
+product AVANCE AVG2302 0x2302 AVG2302
+product AVANCE2 ALG2301 0x2301 ALG2301
+product AVANCE2 ALG2302 0x2302 ALG2302
+
+/* CCUBE products */
+product CCUBE CINEMASTER 0x8888 Cinemaster C 3.0 DVD Decoder
+
+/* AVM products */
+product AVM FRITZ_CARD 0x0a00 Fritz! Card ISDN Interface
+
+/* Bit3 products */
+product BIT3 PCIVME617 0x0001 PCI-VME Interface Mod. 617
+product BIT3 PCIVME618 0x0010 PCI-VME Interface Mod. 618
+product BIT3 PCIVME2706 0x0300 PCI-VME Interface Mod. 2706
+
+/* Broadcom products */
+product BROADCOM BCM4211 0x4211 BCM4211 iLine10 Controller
+product BROADCOM BCM4212 0x4212 BCM4212 V.90 Modem
+product BROADCOM BCM5700 0x1644 BCM5700 10/100/1000 Ethernet
+product BROADCOM BCM5701 0x1645 BCM5701 10/100/1000 Ethernet
+product BROADCOM BCM5702 0x16a6 BCM5702 10/100/1000 Ethernet
+product BROADCOM BCM5703 0x16a7 BCM5703 10/100/1000 Ethernet
+product BROADCOM BCM5705 0x1653 BCM5705 10/100/1000 Ethernet
+product BROADCOM BCM5820 0x5820 BCM5820 eCommerce Processor
+product BROADCOM BCM5821 0x5821 BCM5821 Super-eCommerce Processor
+product BROADCOM BCM5850 0x5850 BCM5850 SSL/TLS Protocol Processor
+
+/* Brooktree products */
+product BROOKTREE BT848 0x0350 Bt848 Video Capture
+product BROOKTREE BT849 0x0351 Bt849 Video Capture
+product BROOKTREE BT878 0x036e Bt878 Video Capture
+product BROOKTREE BT879 0x036f Bt879 Video Capture
+
+/* BusLogic products */
+product BUSLOGIC MULTIMASTER_NC 0x0140 MultiMaster NC
+product BUSLOGIC MULTIMASTER 0x1040 MultiMaster
+product BUSLOGIC FLASHPOINT 0x8130 FlashPoint
+
+/* c't Magazin products */
+product C4T GPPCI 0x6773 GPPCI
+
+/* Chips and Technologies products */
+product CHIPS 64310 0x00b8 64310
+product CHIPS 65545 0x00d8 65545
+product CHIPS 65548 0x00dc 65548
+product CHIPS 65550 0x00e0 65550
+product CHIPS 65554 0x00e4 65554
+
+/* Cirrus Logic products */
+product CIRRUS CL_GD7548 0x0038 CL-GD7548
+product CIRRUS CL_GD5430 0x00a0 CL-GD5430
+product CIRRUS CL_GD5434_4 0x00a4 CL-GD5434-4
+product CIRRUS CL_GD5434_8 0x00a8 CL-GD5434-8
+product CIRRUS CL_GD5436 0x00ac CL-GD5436
+product CIRRUS CL_GD5446 0x00b8 CL-GD5446
+product CIRRUS CL_GD5480 0x00bc CL-GD5480
+product CIRRUS CL_PD6729 0x1100 CL-PD6729
+product CIRRUS CL_PD6832 0x1110 CL-PD6832 PCI-CardBus Bridge
+product CIRRUS CL_PD6833 0x1113 CL-PD6833 PCI-CardBus Bridge
+product CIRRUS CL_GD7542 0x1200 CL-GD7542
+product CIRRUS CL_GD7543 0x1202 CL-GD7543
+product CIRRUS CL_GD7541 0x1204 CL-GD7541
+product CIRRUS CL_CD4400 0x4400 CL-CD4400 Communications Controller
+product CIRRUS CS4610 0x6001 CS4610 SoundFusion Audio Accelerator
+product CIRRUS CS4280 0x6003 CS4280 CrystalClear Audio Interface
+
+/* CMD Technology products -- info gleaned from their web site */
+product CMDTECH 640 0x0640 PCI0640
+/* No data on the CMD Tech. web site for the following as of Mar. 3 '98 */
+product CMDTECH 642 0x0642 PCI0642
+/* datasheets available from www.cmd.com for the followings */
+product CMDTECH 643 0x0643 PCI0643
+product CMDTECH 646 0x0646 PCI0646
+product CMDTECH 647 0x0647 PCI0647
+product CMDTECH 648 0x0648 PCI0648
+product CMDTECH 649 0x0649 PCI0649
+
+/* Inclusion of 'A' in the following entry is probably wrong. */
+/* No data on the CMD Tech. web site for the following as of Mar. 3 '98 */
+product CMDTECH 650A 0x0650 PCI0650A
+product CMDTECH 670 0x0670 USB0670
+product CMDTECH 673 0x0673 USB0673
+
+/* C-Media products */
+product CMEDIA CMI8338A 0x0100 CMI8338A PCI Audio Device
+product CMEDIA CMI8338B 0x0101 CMI8338B PCI Audio Device
+product CMEDIA CMI8738 0x0111 CMI8738/C3DX PCI Audio Device
+product CMEDIA HSP56 0x0211 HSP56 Audiomodem Riser
+
+/* Cogent Data Technologies products */
+product COGENT EM110TX 0x1400 EX110TX PCI Fast Ethernet Adapter
+
+/* Compaq products */
+product COMPAQ PCI_EISA_BRIDGE 0x0001 PCI-EISA Bridge
+product COMPAQ PCI_ISA_BRIDGE 0x0002 PCI-ISA Bridge
+product COMPAQ TRIFLEX1 0x1000 Triflex Host-PCI Bridge
+product COMPAQ TRIFLEX2 0x2000 Triflex Host-PCI Bridge
+product COMPAQ QVISION_V0 0x3032 QVision
+product COMPAQ QVISION_1280P 0x3033 QVision 1280/p
+product COMPAQ QVISION_V2 0x3034 QVision
+product COMPAQ TRIFLEX4 0x4000 Triflex Host-PCI Bridge
+product COMPAQ USB 0x7020 USB Controller
+product COMPAQ SMART2P 0xae10 SMART2P RAID
+product COMPAQ N100TX 0xae32 Netelligent 10/100 TX
+product COMPAQ N10T 0xae34 Netelligent 10 T
+product COMPAQ IntNF3P 0xae35 Integrated NetFlex 3/P
+product COMPAQ DPNet100TX 0xae40 Dual Port Netelligent 10/100 TX
+product COMPAQ IntPL100TX 0xae43 ProLiant Integrated Netelligent 10/100 TX
+product COMPAQ DP4000 0xb011 Deskpro 4000 5233MMX
+product COMPAQ NF3P_BNC 0xf150 NetFlex 3/P w/ BNC
+product COMPAQ NF3P 0xf130 NetFlex 3/P
+
+/* Compex products - XXX better descriptions */
+product COMPEX NE2KETHER 0x1401 Ethernet
+product COMPEX RL100ATX 0x2011 RL100-ATX 10/100 Ethernet
+product COMPEX RL100TX 0x9881 RL100-TX 10/100 Ethernet
+
+/* Conexant Systems products */
+product CONEXANT SOFTK56 0x2443 SoftK56 PCI Software Modem
+
+/* Contaq Microsystems products */
+product CONTAQ 82C599 0x0600 82C599 PCI-VLB Bridge
+product CONTAQ 82C693 0xc693 82C693 PCI-ISA Bridge
+
+/* Corollary Products */
+product COROLLARY CBUSII_PCIB 0x0014 \"C-Bus II\"-PCI Bridge
+
+/* Creative Labs products */
+product CREATIVELABS SBLIVE 0x0002 SBLive! EMU 10000
+product CREATIVELABS SBJOY 0x7002 PCI Gameport Joystick
+product CREATIVELABS EV1938 0x8938 Ectiva 1938
+
+/* Cyclades products */
+product CYCLADES CYCLOMY_1 0x0100 Cyclom-Y below 1M
+product CYCLADES CYCLOMY_2 0x0101 Cyclom-Y above 1M
+product CYCLADES CYCLOM4Y_1 0x0102 Cyclom-4Y below 1M
+product CYCLADES CYCLOM4Y_2 0x0103 Cyclom-4Y above 1M
+product CYCLADES CYCLOM8Y_1 0x0104 Cyclom-8Y below 1M
+product CYCLADES CYCLOM8Y_2 0x0105 Cyclom-8Y above 1M
+product CYCLADES CYCLOMZ_1 0x0200 Cyclom-Z below 1M
+product CYCLADES CYCLOMZ_2 0x0201 Cyclom-Z above 1M
+
+/* Davicom Semiconductor products */
+product DAVICOM DM9102 0x9102 Davicom DM9102 10/100 Ethernet
+
+/* DEC products */
+product DEC 21050 0x0001 DECchip 21050 PCI-PCI Bridge
+product DEC 21040 0x0002 DECchip 21040 Ethernet
+product DEC 21030 0x0004 DECchip 21030 (\"TGA\")
+product DEC NVRAM 0x0007 Zephyr NV-RAM
+product DEC KZPSA 0x0008 KZPSA
+product DEC 21140 0x0009 DECchip 21140 10/100 Ethernet
+product DEC PBXGB 0x000d TGA2
+product DEC DEFPA 0x000f DEFPA
+/* product DEC ??? 0x0010 ??? VME Interface */
+product DEC 21041 0x0014 DECchip 21041 Ethernet
+product DEC DGLPB 0x0016 DGLPB (\"OPPO\")
+product DEC 21142 0x0019 DECchip 21142/21143 10/100 Ethernet
+product DEC 21052 0x0021 DECchip 21052 PCI-PCI Bridge
+product DEC 21150 0x0022 DECchip 21150 PCI-PCI Bridge
+product DEC 21152 0x0024 DECchip 21152 PCI-PCI Bridge
+product DEC 21153 0x0025 DECchip 21153 PCI-PCI Bridge
+product DEC 21154 0x0026 DECchip 21154 PCI-PCI Bridge
+product DEC CPQ42XX 0x0046 Compaq SMART RAID 42xx
+
+/* Delta products */
+product DELTA 8139 0x1360 8139 Ethernet
+
+/* Diamond products */
+product DIAMOND VIPER 0x9001 Viper/PCI
+
+/* D-Link Systems products */
+product DLINK DFE550TX 0x1002 DFE-550TX 10/100 Ethernet
+
+/* Distributed Processing Technology products */
+product DPT SC_RAID 0xa400 SmartCache/SmartRAID
+product DPT RAID_I2O 0xa501 SmartRAID (I2O)
+product DPT MEMCTLR 0x1012 Memory Controller
+
+/* Dolphin products */
+product DOLPHIN PCISCI 0x0658 PCI-SCI Bridge
+
+/* Domex products */
+product DOMEX PCISCSI 0x0001 DMX-3191D
+
+/* ELSA products */
+product ELSA QS1PCI 0x1000 QuickStep 1000 ISDN card
+
+/* Emulex products */
+product EMULEX LPPFC 0x10df \"Light Pulse\" FibreChannel adapter
+
+/* Ensoniq products */
+product ENSONIQ AUDIOPCI 0x5000 AudioPCI
+product ENSONIQ AUDIOPCI97 0x1371 AudioPCI 97
+product ENSONIQ CT5880 0x5880 CT5880
+
+/* Epigram (now Broadcom) products */
+product EPIGRAM BCM4210 0xa0fa BCM4210 iLine10 Controller
+
+/* Essential Communications products */
+product ESSENTIAL RR_HIPPI 0x0001 RoadRunner HIPPI Interface
+product ESSENTIAL RR_GIGE 0x0005 RoadRunner Gig-E Interface
+
+/* ESS Technology Inc products */
+product ESSTECH MAESTRO1 0x0100 Maestro 1 PCI Audio Accelerator
+product ESSTECH MAESTRO2 0x1968 Maestro 2 PCI Audio Accelerator
+product ESSTECH SOLO1 0x1969 Solo-1 PCI AudioDrive
+product ESSTECH MAESTRO2E 0x1978 Maestro 2E PCI Audio Accelerator
+product ESSTECH MAESTRO3 0x1998 Maestro 3 PCI Audio Accelerator
+product ESSTECH MAESTRO3MODEM 0x1999 Maestro 3 Modem
+
+/* ESS Technology Inc products */
+product ESSTECH2 MAESTRO1 0x0100 Maestro 1 PCI Audio Accelerator
+
+/* O2 Micro Inc */
+product O2MICRO OZ6832 0x6832 OZ6832 CardBus Controller
+
+/* Evans & Sutherland products */
+product ES FREEDOM 0x0001 Freedom PCI-GBus Interface
+
+/* FORE products */
+product FORE PCA200 0x0210 ATM PCA-200
+product FORE PCA200E 0x0300 ATM PCA-200e
+
+/* Forte Media products */
+product FORTEMEDIA FM801 0x0801 Forte Media 801 Sound
+
+/* Future Domain products */
+product FUTUREDOMAIN TMC_18C30 0x0000 TMC-18C30 (36C70)
+
+/* Efficient Networks products */
+product EFFICIENTNETS ENI155PF 0x0000 155P-MF1 ATM (FPGA)
+product EFFICIENTNETS ENI155PA 0x0002 155P-MF1 ATM (ASIC)
+product EFFICIENTNETS ENI25P 0x0003 SpeedStream ENI-25p
+product EFFICIENTNETS SS3000 0x0005 SpeedStream 3000
+
+/* Galileo Technology products */
+product GALILEO GT64010A 0x0146 GT-64010A System Controller
+product GALILEO GT64115 0x4111 GT-64115 System Controller
+product GALILEO GT64011 0x4146 GT-64011 System Controller
+product GALILEO GT64120 0x4620 GT-64120 System Controller
+product GALILEO GT64130 0x6320 GT-64130 System Controller
+
+/* Hewlett-Packard products */
+product HP J2585A 0x1030 J2585A
+
+/* IBM products */
+product IBM MCABRIDGE 0x0002 MCA Bridge
+product IBM ALTALITE 0x0005 CPU Bridge - Alta Lite
+product IBM ALTAMP 0x0007 CPU Bridge - Alta MP
+product IBM ISABRIDGE 0x000a ISA Bridge w/PnP
+product IBM CPUBRIDGE 0x0017 CPU Bridge
+product IBM LANSTREAMER 0x0018 Auto LANStreamer
+product IBM GXT150P 0x001b GXT-150P 2D Accelerator
+product IBM MCABRIDGE2 0x0020 MCA Bridge
+product IBM 82351 0x0022 82351 PCI-PCI Bridge
+product IBM SERVERAID 0x002e ServeRAID
+product IBM OLYMPIC 0x003e Token Ring
+product IBM MIAMI 0x0036 Miami/PCI
+product IBM TURBOWAYS25 0x0053 Turboways 25 ATM
+product IBM MPIC2 0xffff MPIC-II
+
+/* IDT products */
+product IDT 77201 0x0001 77201/77211 ATM (\"NICStAR\")
+
+/* Initio products */
+product INITIO I920 0x0002 INIC-920 SCSI
+product INITIO I940 0x9400 INIC-940 SCSI
+product INITIO I935 0x9401 INIC-935 SCSI
+product INITIO I950 0x9500 INIC-950 SCSI
+
+/* Integrated Micro Solutions products */
+product IMS 8849 0x8849 8849
+product IMS TT128M 0x9128 TwinTurbo 128M
+
+/* Intel products */
+product INTEL PCEB 0x0482 82375EB/SB PCI-EISA Bridge (PCEB)
+product INTEL CDC 0x0483 82424ZX Cache and DRAM controller (CDC)
+product INTEL SIO 0x0484 82378ZB System I/O (SIO)
+product INTEL 82426EX 0x0486 82426EX PCI-to-ISA Bridge (PCIB)
+product INTEL PCMC 0x04a3 82434LX/NX PCI, Cache and Memory Controller (PCMC)
+product INTEL IN_BUSINESS 0x1030 InBusiness Fast Ethernet LAN Controller
+product INTEL 82559ER 0x1209 82559ER Fast Ethernet LAN Controller
+product INTEL 82092AA 0x1222 82092AA IDE controller
+product INTEL SAA7116 0x1223 SAA7116
+product INTEL 82596 0x1226 82596 LAN Controller
+product INTEL EEPRO100 0x1227 EE Pro 100 10/100 Fast Ethernet
+product INTEL EEPRO100S 0x1228 EE Pro 100 Smart 10/100 Fast Ethernet
+product INTEL 82557 0x1229 82557 Fast Ethernet LAN Controller
+product INTEL 82437FX 0x122d 82437FX System Controller (TSC)
+product INTEL 82371FB_ISA 0x122e 82371FB PCI-to-ISA Bridge (PIIX)
+product INTEL 82371FB_IDE 0x1230 82371FB IDE controller (PIIX)
+product INTEL 82371MX 0x1234 82371MX Mobile PCI I/O IDE Xcelerator (MPIIX)
+product INTEL 82437MX 0x1235 82437MX Mobile System Controller (MTSC)
+product INTEL 82441FX 0x1237 82441FX PCI and Memory Controller (PMC)
+product INTEL 82380AB 0x123c 82380AB Mobile PCI-to-ISA Bridge (MISA)
+product INTEL 82380FB 0x124b 82380FB Mobile PCI-to-PCI Bridge (MPCI2)
+product INTEL 82439HX 0x1250 82439HX System Controller (TXC)
+product INTEL 82801AA_LPC 0x2410 82801AA LPC Interface Bridge
+product INTEL 82801AA_IDE 0x2411 82801AA IDE Controller
+product INTEL 82801AA_USB 0x2412 82801AA USB Controller
+product INTEL 82801AA_SMB 0x2413 82801AA SMBus Controller
+product INTEL 82801AA_ACA 0x2415 82801AA AC-97 Audio Controller
+product INTEL 82801AA_ACM 0x2416 82801AA AC-97 PCI Modem
+product INTEL 82801AA_HPB 0x2418 82801AA Hub-to-PCI Bridge
+product INTEL 82801AB_LPC 0x2420 82801AB LPC Interface Bridge
+product INTEL 82801AB_IDE 0x2421 82801AB IDE Controller
+product INTEL 82801AB_USB 0x2422 82801AB USB Controller
+product INTEL 82801AB_SMB 0x2423 82801AB SMBus Controller
+product INTEL 82801AB_ACA 0x2425 82801AB AC-97 Audio Controller
+product INTEL 82801AB_ACM 0x2426 82801AB AC-97 PCI Modem
+product INTEL 82801AB_HPB 0x2428 82801AB Hub-to-PCI Bridge
+product INTEL 82801BA_LPC 0x2440 82801BA LPC Interface Bridge
+product INTEL 82801BA_USB1 0x2442 82801BA USB Controller
+product INTEL 82801BA_SMB 0x2443 82801BA SMBus Controller
+product INTEL 82801BA_USB2 0x2444 82801BA USB Controller
+product INTEL 82801BA_ACA 0x2445 82801BA AC-97 Audio Controller
+product INTEL 82801BA_ACM 0x2446 82801BA AC-97 PCI Modem
+product INTEL 82801BA_LAN 0x2449 82801BA LAN Controller
+product INTEL 82801BA_IDE 0x244B 82801BA IDE Controller
+product INTEL 82801BA_HPB 0x244E 82801BA Hub-to-PCI Bridge
+product INTEL 82371SB_ISA 0x7000 82371SB PCI-to-ISA Bridge (PIIX3)
+product INTEL 82371SB_IDE 0x7010 82371SB IDE Interface (PIIX3)
+product INTEL 82371SB_USB 0x7020 82371SB USB Host Controller (PIIX3)
+product INTEL 82437VX 0x7030 82437VX System Controller (TVX)
+product INTEL 82439TX 0x7100 82439TX System Controller (MTXC)
+product INTEL 82371AB_ISA 0x7110 82371AB PCI-to-ISA Bridge (PIIX4)
+product INTEL 82371AB_IDE 0x7111 82371AB IDE controller (PIIX4)
+product INTEL 82371AB_USB 0x7112 82371AB USB Host Controller (PIIX4)
+product INTEL 82371AB_PMC 0x7113 82371AB Power Management Controller (PIIX4)
+product INTEL 82810_MCH 0x7120 82810 Memory Controller Hub
+product INTEL 82810_GC 0x7121 82810 Graphics Controller
+product INTEL 82810_DC100_MCH 0x7122 82810-DC100 Memory Controller Hub
+product INTEL 82810_DC100_GC 0x7123 82810-DC100 Graphics Controller
+product INTEL 82810E_MCH 0x7124 82810E Memory Controller Hub
+product INTEL 82810E_GC 0x7125 82810E Graphics Controller
+product INTEL 82443LX 0x7180 82443LX PCI AGP Controller (PAC)
+product INTEL 82443LX_AGP 0x7181 82443LX AGP Interface (PAC)
+product INTEL 82443BX 0x7190 82443BX Host Bridge/Controller
+product INTEL 82443BX_AGP 0x7191 82443BX AGP Interface
+product INTEL 82443BX_NOAGP 0x7192 82443BX Host Bridge/Controller (AGP disabled)
+product INTEL 82440MX 0x7194 82440MX Host Bridge/Controller
+product INTEL 82440MX_ACA 0x7195 82440MX AC-97 Audio Controller
+product INTEL 82440MX_ISA 0x7198 82440MX PCI-to-ISA Bridge
+product INTEL 82440MX_IDE 0x7199 82440MX IDE Controller
+product INTEL 82440MX_USB 0x719a 82440MX USB Host Controller
+product INTEL 82440MX_PMC 0x719b 82440MX Power Management Controller
+product INTEL I740 0x7800 i740 Graphics Accelerator
+product INTEL PCI450_PB 0x84c4 82454KX/GX PCI Bridge (PB)
+product INTEL PCI450_MC 0x84c5 82451KX/GX Memory Controller (MC)
+product INTEL 82451NX_MIOC 0x84ca 82451NX Memory & I/O Controller (MIOC)
+product INTEL 82451NX_PXB 0x84cb 82451NX PCI Expander Bridge (PXB)
+
+/* Intergraph products */
+product INTERGRAPH 4D50T 0x00e4 Powerstorm 4D50T
+
+/* I. T. T. products */
+product ITT AGX016 0x0001 AGX016
+product ITT ITT3204 0x0002 ITT3204 MPEG Decoder
+
+/* KTI products - XXX better descriptions */
+product KTI NE2KETHER 0x3000 Ethernet
+
+/* LAN Media Corporation */
+product LMC HSSI 0x0003 HSSI Interface
+product LMC DS3 0x0004 DS3 Interface
+product LMC SSI 0x0005 SSI
+
+/* LeadTek Research */
+product LEADTEK S3_805 0x0000 S3 805
+
+/* Linear Systems / CompuModules */
+product LINEARSYS DVB_TX 0x7629 DVB Transmitter
+product LINEARSYS DVB_RX 0x7630 DVB Receiver
+
+/* Lite-On products */
+product LITEON 82C168 0x0002 82C168/82C169 (PNIC) 10/100 Ethernet
+product LITEON 82C115 0xc115 82C115 (PNIC II) 10/100 Ethernet
+
+/* Lucent products */
+product LUCENT LTMODEM_0440 0x0440 K56flex DSVD LTMODEM
+product LUCENT LTMODEM_0441 0x0441 LTMODEM
+product LUCENT LTMODEM_0442 0x0442 LTMODEM
+product LUCENT LTMODEM_0443 0x0443 LTMODEM
+product LUCENT LTMODEM_0444 0x0444 LTMODEM
+product LUCENT LTMODEM_0445 0x0445 LTMODEM
+product LUCENT LTMODEM_0446 0x0446 LTMODEM
+product LUCENT LTMODEM_0447 0x0447 LTMODEM
+product LUCENT LTMODEM_0448 0x0448 LTMODEM
+product LUCENT LTMODEM_0449 0x0449 LTMODEM
+product LUCENT LTMODEM_044A 0x044A LTMODEM
+product LUCENT LTMODEM_044B 0x044B LTMODEM
+product LUCENT LTMODEM_044C 0x044C LTMODEM
+product LUCENT LTMODEM_044D 0x044D LTMODEM
+product LUCENT LTMODEM_044E 0x044E LTMODEM
+product LUCENT LTMODEM_0450 0x0450 LTMODEM
+product LUCENT LTMODEM_0451 0x0451 LTMODEM
+product LUCENT LTMODEM_0452 0x0452 LTMODEM
+product LUCENT LTMODEM_0453 0x0453 LTMODEM
+product LUCENT LTMODEM_0454 0x0454 LTMODEM
+product LUCENT LTMODEM_0455 0x0455 LTMODEM
+product LUCENT LTMODEM_0456 0x0456 LTMODEM
+product LUCENT LTMODEM_0457 0x0457 LTMODEM
+product LUCENT LTMODEM_0458 0x0458 LTMODEM
+product LUCENT LTMODEM_0459 0x0459 LTMODEM
+product LUCENT LTMODEM_045A 0x045A LTMODEM
+product LUCENT USBHC 0x5801 USB Host Controller
+
+/* Macronix */
+product MACRONIX MX98713 0x0512 MX98713 (PMAC) 10/100 Ethernet
+product MACRONIX MX987x5 0x0531 MX987x5 (PMAC) 10/100 Ethernet
+
+/* Madge Networks products */
+product MADGE COLLAGE25 0x1000 Collage 25 ATM adapter
+product MADGE COLLAGE155 0x1001 Collage 155 ATM adapter
+
+/* Matrox products */
+product MATROX ATLAS 0x0518 MGA PX2085 (\"Atlas\")
+product MATROX MILLENNIUM 0x0519 MGA Millennium 2064W
+product MATROX MYSTIQUE 0x051a MGA Mystique 1064SG
+product MATROX MILLENNIUM2 0x051b MGA Millennium II 2164W
+product MATROX MILLENNIUM2_AGP 0x051f MGA Millennium II 2164WA-B AG
+product MATROX G200_PCI 0x0520 MGA G200 PCI
+product MATROX G200_AGP 0x0521 MGA G200 AGP
+product MATROX G400_AGP 0x0525 MGA G400 AGP
+product MATROX IMPRESSION 0x0d10 MGA Impression
+product MATROX G100_PCI 0x1000 MGA G100 PCI
+product MATROX G100_AGP 0x1001 MGA G100 AGP
+
+/* Motorola products */
+product MOT MPC105 0x0001 MPC105 \"Eagle\" Host Bridge
+product MOT MPC106 0x0002 MPC106 \"Grackle\" Host Bridge
+
+/* Mylex products */
+product MYLEX 960P 0x0001 DAC960P RAID controller
+
+/* Mutech products */
+product MUTECH MV1000 0x0001 MV1000
+
+/* NetVin products - XXX better descriptions */
+product NETVIN 5000 0x5000 5000 Ethernet
+
+/* Newbridge / Tundra products */
+product NEWBRIDGE CA91CX42 0x0000 Universe VME bridge
+
+/* National Semiconductor products */
+product NS DP83810 0x0001 DP83810 10/100 Ethernet
+product NS DP83815 0x0020 DP83815 10/100 Ethernet
+product NS NS87410 0xd001 NS87410
+
+/* NCR/Symbios Logic products */
+product SYMBIOS 810 0x0001 53c810
+product SYMBIOS 820 0x0002 53c820
+product SYMBIOS 825 0x0003 53c825
+product SYMBIOS 815 0x0004 53c815
+product SYMBIOS 810AP 0x0005 53c810AP
+product SYMBIOS 860 0x0006 53c860
+product SYMBIOS 896 0x000b 53c896
+product SYMBIOS 895 0x000c 53c895
+product SYMBIOS 885 0x000d 53c885
+product SYMBIOS 875 0x000f 53c875
+product SYMBIOS 1510 0x0010 53c1510
+product SYMBIOS 875J 0x008f 53c875J
+
+/* Packet Engines products */
+product SYMBIOS PE_GNIC 0x0702 Packet Engines G-NIC Ethernet
+
+/* NEC products */
+product NEC USB 0x0035 USB Host Controller
+product NEC POWERVR2 0x0046 PowerVR PCX2
+product NEC PD72872 0x0063 uPD72872 IEEE 1394 OHCI Host Controller
+product NEC PD72870 0x00cd uPD72870 IEEE 1394 OHCI Host Controller
+product NEC PD72871 0x00ce uPD72871 IEEE 1394 OHCI Host Controller
+
+/* Neomagic products */
+product NEOMAGIC NMMG128ZV 0x0003 MagicGraph 128ZV
+product NEOMAGIC NMMG2160 0x0004 MagicGraph 128XD
+product NEOMAGIC NMMM256AV_VGA 0x0005 MagicMedia 256AV VGA
+product NEOMAGIC NMMM256ZX_VGA 0x0006 MagicMedia 256ZX VGA
+product NEOMAGIC NMMM256AV_AU 0x8005 MagicMedia 256AV Audio
+product NEOMAGIC NMMM256ZX_AU 0x8006 MagicMedia 256ZX Audio
+
+/* Netgear products */
+product NETGEAR GA620 0x620a GA620 Gigabit Ethernet
+
+/* NexGen products */
+product NEXGEN NX82C501 0x4e78 NX82C501 Host-PCI Bridge
+
+/* NKK products */
+product NKK NDR4600 0xA001 NDR4600 Host-PCI Bridge
+
+/* Number Nine products */
+product NUMBER9 I128 0x2309 Imagine-128
+product NUMBER9 I128_2 0x2339 Imagine-128 II
+
+/* Nvidia Corporationn products */
+product NVIDIA RIVATNT 0x0020 RIVA TNT
+product NVIDIA RIVATNT2 0x0028 RIVA TNT2
+product NVIDIA RIVATNT2U 0x0029 RIVA TNT2 Ultra
+product NVIDIA VANTA 0x002C Vanta
+product NVIDIA RIVATNT2M64 0x002D RIVA TNT2 Model 64
+product NVIDIA ALADDINTNT2 0x00A0 Aladdin TNT2
+product NVIDIA GEFORCE256 0x0100 GeForce 256
+product NVIDIA GEFORCEDDR 0x0101 GeForce DDR
+product NVIDIA QUADRO 0x0103 Quadro
+product NVIDIA GEFORCE2 0x0150 GeForce2 GTS
+product NVIDIA GEFORCE2DDR 0x0151 GeForce2 GTS (DDR)
+product NVIDIA GEFORCE2BR 0x0152 GeForce2 GTS
+product NVIDIA QUADRO2 0x0153 Quadro2
+
+/* Nvidia Corporation & SGS Thomson Microelectric */
+product NVIDIA_SGS RIVA128 0x0018 Riva 128
+
+/* Oak Technologies products */
+product OAKTECH OTI1007 0x0107 OTI107
+
+/* Olicom products */
+product OLICOM OC2183 0x0013 Olicom OC-2183/2185 Ethernet
+product OLICOM OC2325 0x0012 Olicom OC-2325 Ethernet
+product OLICOM OC2326 0x0014 Olicom OC-2326 10/100-TX Ethernet
+
+/* Opti products */
+product OPTI 82C557 0xc557 82C557
+product OPTI 82C558 0xc558 82C558
+product OPTI 82C568 0xc568 82C568
+product OPTI 82D568 0xd568 82D568
+product OPTI 82C621 0xc621 82C621
+product OPTI 82C822 0xc822 82C822
+product OPTI RM861HA 0xc861 RM861HA
+product OPTI 82C700 0xc700 82C700
+product OPTI 82C701 0xc701 82C701
+
+/* PC Tech products */
+product PCTECH RZ1000 0x1000 RZ1000
+
+/* PLX Technology products */
+product PLX 9060ES 0x906e 9060ES PCI bus controller
+
+/* ProLAN products - XXX better descriptions */
+product PROLAN NE2KETHER 0x1980 Ethernet
+
+/* Promise products */
+product PROMISE DC5030 0x5300 DC5030
+product PROMISE ULTRA33 0x4d33 Ultra33/ATA Bus Master IDE Accelerator
+product PROMISE ULTRA66 0x4d38 Ultra66/ATA Bus Master IDE Accelerator
+product PROMISE ULTRA100 0x4d30 Ultra100/ATA Bus Master IDE Accelerator
+
+/* QLogic products */
+product QLOGIC ISP1020 0x1020 ISP1020
+product QLOGIC ISP1022 0x1022 ISP1022
+product QLOGIC ISP1080 0x1080 ISP1080
+product QLOGIC ISP1240 0x1240 ISP1240
+product QLOGIC ISP2100 0x2100 ISP2100
+
+/* Quantum Designs products */
+product QUANTUMDESIGNS 8500 0x0001 8500
+product QUANTUMDESIGNS 8580 0x0002 8580
+
+/* Realtek (Creative Labs?) products */
+product REALTEK RT8029 0x8029 8029 Ethernet
+product REALTEK RT8129 0x8129 8129 10/100 Ethernet
+product REALTEK RT8139 0x8139 8139 10/100 Ethernet
+
+/* RICOH products */
+product RICOH Rx5C465 0x0465 5C465 PCI-CardBus bridge
+product RICOH Rx5C466 0x0466 5C466 PCI-CardBus bridge
+product RICOH Rx5C475 0x0475 5C475 PCI-CardBus bridge
+product RICOH RL5C476 0x0476 5C476 PCI-CardBus bridge
+product RICOH Rx5C477 0x0477 5C477 PCI-CardBus bridge
+product RICOH Rx5C478 0x0478 5C478 PCI-CardBus bridge
+
+/* RISCom (SDL Communications, Inc?) products */
+product RISCOM N2 0x5568 N2
+
+/* RNS products */
+product RNS FDDI 0x2200 2200 FDDI
+
+/* S3 products */
+product S3 VIRGE 0x5631 ViRGE
+product S3 TRIO32 0x8810 Trio32
+product S3 TRIO64 0x8811 Trio32/64
+product S3 AURORA64P 0x8812 Aurora64V+
+product S3 TRIO64UVP 0x8814 Trio64UV+
+product S3 VIRGE_VX 0x883d ViRGE/VX
+product S3 868 0x8880 868
+product S3 928 0x88b0 86C928
+product S3 864_0 0x88c0 86C864-0
+product S3 864_1 0x88c1 86C864-1
+product S3 864_2 0x88c2 86C864-2
+product S3 864_3 0x88c3 86C864-3
+product S3 964_0 0x88d0 86C964-0
+product S3 964_1 0x88d1 86C964-1
+product S3 964_2 0x88d2 86C964-2
+product S3 964_3 0x88d3 86C964-3
+product S3 968_0 0x88f0 86C968-0
+product S3 968_1 0x88f1 86C968-1
+product S3 968_2 0x88f2 86C968-2
+product S3 968_3 0x88f3 86C968-3
+product S3 TRIO64V2_DX 0x8901 Trio64V2/DX
+product S3 PLATO_PX 0x8901 Plato/PX
+product S3 TRIO3D 0x8904 86C365 Trio3D
+product S3 VIRGE_DX 0x8a01 ViRGE/DX
+product S3 VIRGE_GX2 0x8a10 ViRGE/GX2
+product S3 TRIO3D2X 0x8a13 Trio3D/2X
+product S3 SAVAGE3D 0x8a20 Savage3D
+product S3 SAVAGE3D_MV 0x8a21 Savage3D+MV
+product S3 SAVAGE4 0x8a22 Savage4
+product S3 VIRGE_MX 0x8c01 ViRGE/MX
+product S3 VIRGE_MXP 0x8c03 ViRGE/MXP
+product S3 SAVAGE_MX_MV 0x8c10 Savage/MX+MV
+product S3 SAVAGE_MX 0x8c11 Savage/MX
+product S3 SAVAGE_IX_MV 0x8c12 Savage/IX+MV
+product S3 SAVAGE_IX 0x8c13 Savage/IX
+product S3 SAVAGE2000 0x9102 Savage2000
+product S3 SONICVIBES 0xca00 SonicVibes
+
+/* Samsung Semiconductor products */
+product SAMSUNGSEMI KS8920 0x8920 KS8920 10/100 Ethernet
+
+/* SGI products */
+product SGI IOC3 0x0003 IOC3
+product SGI RAD1 0x0005 PsiTech RAD1
+product SGI TIGON 0x0009 Tigon Gigabit Ethernet
+
+/* SGS Thomson products */
+product SGSTHOMSON 2000 0x0008 STG 2000X
+product SGSTHOMSON 1764 0x1746 STG 1764X
+
+/* SiByte, Inc. products */
+product SIBYTE SB1250_PCI 0x0001 BCM1250 PCI Host Bridge
+product SIBYTE SB1250_LDT 0x0002 BCM1250 HyperTransport Host Bridge
+
+/* Sigma Designs products */
+product SIGMA HOLLYWOODPLUS 0x8300 REALmagic Hollywood-Plus MPEG-2 Decoder
+
+/* Silicon Integrated System products */
+product SIS 86C201 0x0001 86C201
+product SIS 86C202 0x0002 86C202
+product SIS 86C205 0x0005 86C205
+product SIS 85C503 0x0008 85C503 or 5597/5598 ISA bridge
+product SIS 600PMC 0x0009 600 Power Mngmt Controller
+product SIS 5597_VGA 0x0200 5597/5598 integrated VGA
+product SIS 85C501 0x0406 85C501
+product SIS 85C496 0x0496 85C496
+product SIS 530HB 0x0530 530 Host to PCI Bridge
+product SIS 85C601 0x0601 85C601
+product SIS 900 0x0900 SiS 900 10/100 Ethernet
+product SIS 5597_IDE 0x5513 5597/5598 IDE controller
+product SIS 5597_HB 0x5597 5597/5598 host bridge
+product SIS 530VGA 0x6306 530 GUI Accelerator+3D
+product SIS 6326 0x6326 6326 AGP VGA
+product SIS 5597_USB 0x7001 5597/5598 USB host controller
+product SIS 7016 0x7016 SiS 7016 10/100 Ethernet
+
+/* Silicon Motion products */
+product SILMOTION LYNX_E 0x0810 Lynx E
+
+/* SMC products */
+product SMC 37C665 0x1000 FDC 37C665
+product SMC 37C922 0x1001 FDC 37C922
+product SMC 83C170 0x0005 83C170 (\"EPIC/100\") Fast Ethernet
+product SMC 83C175 0x0006 83C175 (\"EPIC/100\") Fast Ethernet
+
+/* Solidum Systems Corporation */
+product SOLIDUM AMD971 0x2000 SNP8023: AMD 971
+product SOLIDUM CLASS802 0x8023 SNP8023: Classifier Engine
+
+/* Sony products */
+product SONY CXD1947A 0x8009 CXD1947A IEEE 1394 Host Controller
+product SONY CXD32222 0x8039 CXD3222 OHCI IEEE 1394 Host Controller
+product SONY MEMSTICK 0x808a Memory Stick I/F Controller
+
+/* Sun Microsystems products */
+product SUN EBUS 0x1000 PCIO Ebus2
+product SUN HMENETWORK 0x1001 PCIO Happy Meal Ethernet
+product SUN SIMBA 0x5000 Simba PCI bridge
+product SUN MS_IIep 0x9000 microSPARC IIep PCI
+product SUN US_IIi 0xa000 UltraSPARC IIi PCI
+
+/* Sundance Technology products */
+product SUNDANCETI ST201 0x0201 ST201 10/100 Ethernet
+
+/* Surecom Technology products */
+product SURECOM NE34 0x0e34 NE-34 Ethernet
+
+/* Symphony Labs products */
+product SYMPHONY 82C101 0x0001 82C101
+product SYMPHONY 82C103 0x0103 82C103
+product SYMPHONY 82C105 0x0105 82C105
+product SYMPHONY2 82C101 0x0001 82C101
+product SYMPHONY 83C553 0x0565 83C553 PCI-ISA Bridge
+
+/* Schneider & Koch (really SysKonnect) products */
+product SCHNEIDERKOCH SKNET_FDDI 0x4000 SK-NET FDDI-xP
+
+/* Tekram Technology products (1st PCI Vendor ID)*/
+product TEKRAM DC290 0xdc29 DC-290(M)
+
+/* Tekram Technology products (2nd PCI Vendor ID) */
+product TEKRAM2 DC690C 0x690c DC-690C
+
+/* Texas Instruments products */
+product TI TLAN 0x0500 TLAN
+product TI TVP4020 0x3d07 TVP4020 Permedia 2
+product TI TSB12LV21 0x8000 TSB12LV21 IEEE 1394 Host Controller
+product TI TSB12LV22 0x8009 TSB12LV22 OHCI IEEE 1394 Host Controller
+product TI TSB12LV23 0x8019 TSB12LV23 OHCI IEEE 1394 Host Controller
+product TI TSB12LV26 0x8020 TSB12LV26 OHCI IEEE 1394 Host Controller
+product TI PCI1130 0xac12 PCI1130 PCI-CardBus Bridge
+product TI PCI1031 0xac13 PCI1031 PCI-PCMCIA Bridge
+product TI PCI1131 0xac15 PCI1131 PCI-CardBus Bridge
+product TI PCI1250 0xac16 PCI1250 PCI-CardBus Bridge
+product TI PCI1220 0xac17 PCI1220 PCI-CardBus Bridge
+product TI PCI1221 0xac19 PCI1221 PCI-CardBus Bridge
+product TI PCI1450 0xac1b PCI1450 PCI-CardBus Bridge
+product TI PCI1225 0xac1c PCI1225 PCI-CardBus Bridge
+product TI PCI1251 0xac1d PCI1251 PCI-CardBus Bridge
+product TI PCI1211 0xac1e PCI1211 PCI-CardBus Bridge
+product TI PCI1251B 0xac1f PCI1251B PCI-CardBus Bridge
+product TI PCI2030 0xac20 PCI2030 PCI-PCI Bridge
+product TI PCI1420 0xac51 PCI1420 PCI-CardBus Bridge
+product TI PCI1451 0xac52 PCI1451 PCI-CardBus Bridge
+
+/* Toshiba America products */
+product TOSHIBA R4X00 0x0009 R4x00 Host-PCI Bridge
+product TOSHIBA TC35856F 0x0020 TC35856F ATM (\"Meteor\")
+
+/* Toshiba America Info Systems products */
+product TOSHIBA2 HOST 0x0601 Host Bridge/Controller
+product TOSHIBA2 ISA 0x0602 ISA Bridge
+product TOSHIBA2 ToPIC95 0x0603 ToPIC95 CardBus-PCI Bridge
+product TOSHIBA2 ToPIC95B 0x060a ToPIC95B CardBus-PCI Bridge
+product TOSHIBA2 ToPIC97 0x060f ToPIC97 CardBus-PCI Bridge
+product TOSHIBA2 ToPIC100 0x0617 ToPIC100 CardBus-PCI Bridge
+product TOSHIBA2 FIRO 0x0701 Fast Infrared Type O
+
+/* Trident products */
+product TRIDENT CYBERBLADE_I7 0x8420 CyberBlade i7
+product TRIDENT TGUI_9320 0x9320 TGUI 9320
+product TRIDENT TGUI_9350 0x9350 TGUI 9350
+product TRIDENT TGUI_9360 0x9360 TGUI 9360
+product TRIDENT CYBER_9397 0x9397 CYBER 9397
+product TRIDENT CYBER_9397DVD 0x939a CYBER 9397DVD
+product TRIDENT CYBER_9525 0x9525 CYBER 9525
+product TRIDENT TGUI_9420 0x9420 TGUI 9420
+product TRIDENT TGUI_9440 0x9440 TGUI 9440
+product TRIDENT TGUI_9660 0x9660 TGUI 9660
+product TRIDENT TGUI_9680 0x9680 TGUI 9680
+product TRIDENT TGUI_9682 0x9682 TGUI 9682
+
+/* Triones Technologies products */
+/* The 366 and 370 controllers have the same product ID */
+product TRIONES HPT366 0x0004 HPT366/370 IDE Controller
+
+/* TriTech Microelectronics products*/
+product TRITECH TR25202 0xfc02 Pyramid3D TR25202
+
+/* Tseng Labs products */
+product TSENG ET4000_W32P_A 0x3202 ET4000w32p rev A
+product TSENG ET4000_W32P_B 0x3205 ET4000w32p rev B
+product TSENG ET4000_W32P_C 0x3206 ET4000w32p rev C
+product TSENG ET4000_W32P_D 0x3207 ET4000w32p rev D
+product TSENG ET6000 0x3208 ET6000
+
+/* UMC products */
+product UMC UM82C881 0x0001 UM82C881 486 Chipset
+product UMC UM82C886 0x0002 UM82C886 ISA Bridge
+product UMC UM8673F 0x0101 UM8673F EIDE Controller
+product UMC UM8881 0x0881 UM8881 HB4 486 PCI Chipset
+product UMC UM82C891 0x0891 UM82C891
+product UMC UM886A 0x1001 UM886A
+product UMC UM8886BF 0x673a UM8886BF
+product UMC UM8710 0x8710 UM8710
+product UMC UM8886 0x886a UM8886
+product UMC UM8881F 0x8881 UM8881F PCI-Host bridge
+product UMC UM8886F 0x8886 UM8886F PCI-ISA bridge
+product UMC UM8886A 0x888a UM8886A
+product UMC UM8891A 0x8891 UM8891A
+product UMC UM9017F 0x9017 UM9017F
+product UMC UM8886N 0xe88a UM8886N
+product UMC UM8891N 0xe891 UM8891N
+
+/* ULSI Systems products */
+product ULSI US201 0x0201 US201
+
+/* US Robotics products */
+product USR 3CP5609 0x1008 3CP5609 PCI 16550 Modem
+
+/* V3 Semiconductor products */
+product V3 V292PBC 0x0292 V292PBC AMD290x0 Host-PCI Bridge
+product V3 V960PBC 0x0960 V960PBC i960 Host-PCI Bridge
+product V3 V96DPC 0xC960 V96DPC i960 (Dual) Host-PCI Bridge
+
+/* VIA Technologies products, from http://www.via.com.tw/ */
+product VIATECH VT8371_HB 0x0391 VT8371 (Apollo KX133) Host Bridge
+product VIATECH VT8501_MVP4 0x0501 VT8501 MVP4 System Controller
+product VIATECH VT82C505 0x0505 VT82C505 (Pluto)
+product VIATECH VT82C561 0x0561 VT82C561
+product VIATECH VT82C586A_IDE 0x0571 VT82C586A IDE Controller
+product VIATECH VT82C576 0x0576 VT82C576 3V
+product VIATECH VT82C580VP 0x0585 VT82C580 (Apollo VP) Host-PCI Bridge
+product VIATECH VT82C586_ISA 0x0586 VT82C586 (Apollo VP) PCI-ISA Bridge
+product VIATECH VT82C595 0x0595 VT82C595 (Apollo VP2) Host-PCI Bridge
+product VIATECH VT82C596A 0x0596 VT82C596A (Apollo Pro) PCI-ISA Bridge
+product VIATECH VT82C597 0x0597 VT82C597 (Apollo VP3) Host-PCI Bridge
+product VIATECH VT82C598PCI 0x0598 VT82C598 (Apollo MVP3) Host-PCI
+product VIATECH VT82C686A_ISA 0x0686 VT82C686A (Apollo KX133) PCI-ISA Bridge
+product VIATECH VT82C691 0x0691 VT82C691 (Apollo Pro) Host-PCI
+product VIATECH VT82C693 0x0693 VT82C693 (Apollo Pro Plus) Host-PCI
+product VIATECH VT86C926 0x0926 VT86C926 Amazon PCI-Ethernet Controller
+product VIATECH VT82C570M 0x1000 VT82C570M (Apollo) Host-PCI Bridge
+product VIATECH VT82C570MV 0x1006 VT82C570M (Apollo) PCI-ISA Bridge
+product VIATECH VT82C586_IDE 0x1571 VT82C586 (Apollo VP) IDE Controller
+product VIATECH VT82C595_2 0x1595 VT82C595 (Apollo VP2) Host-PCI Bridge
+product VIATECH VT83C572 0x3038 VT83C572 USB Controller
+product VIATECH VT82C586_PWR 0x3040 VT82C586 (Apollo VP) Power Management Controller
+product VIATECH VT3043 0x3043 VT3043 (Rhine) 10/100 Ethernet
+product VIATECH VT82C686A_SMB 0x3057 VT82C686A SMBus Controller
+product VIATECH VT82C686A_AC97 0x3058 VT82C686A AC-97 Audio Controller
+product VIATECH VT82C686A_MC97 0x3068 VT82C686A MC-97 Modem Controller
+product VIATECH VT86C100A 0x6100 VT86C100A (Rhine-II) 10/100 Ethernet
+product VIATECH VT8371_PPB 0x8391 VT8371 (Apollo KX133) PCI-PCI Bridge
+product VIATECH VT8501AGP 0x8501 VT8501 PCI-AGP
+product VIATECH VT82C597AGP 0x8597 VT82C597 (Apollo VP3) PCI-AGP
+product VIATECH VT82C598AGP 0x8598 VT82C598 (Apollo MVP3) PCI-AGP
+
+/* Vortex Computer Systems products */
+/* GDT_PCI */
+product VORTEX GDT_60x0 0x0000 GDT6000/6020/6050
+product VORTEX GDT_6000B 0x0001 GDT6000B/6010
+/* GDT_PCINEW */
+product VORTEX GDT_6x10 0x0002 GDT6110/6510
+product VORTEX GDT_6x20 0x0003 GDT6120/6520
+product VORTEX GDT_6530 0x0004 GDT6530
+product VORTEX GDT_6550 0x0005 GDT6550
+/* GDT_PCINEW, wide/ultra SCSI controllers */
+product VORTEX GDT_6x17 0x0006 GDT6117/6517
+product VORTEX GDT_6x27 0x0007 GDT6127/6527
+product VORTEX GDT_6537 0x0008 GDT6537
+product VORTEX GDT_6557 0x0009 GDT6557/6557-ECC
+/* GDT_PCINEW, wide SCSI controllers */
+product VORTEX GDT_6x15 0x0010 GDT6115/6515
+product VORTEX GDT_6x25 0x0011 GDT6125/6525
+product VORTEX GDT_6535 0x0012 GDT6535
+product VORTEX GDT_6555 0x0013 GDT6555/6555-ECC
+/* GDT_MPR, RP series, wide/ultra SCSI */
+product VORTEX GDT_6x17RP 0x0100 GDT6117RP/GDT6517RP
+product VORTEX GDT_6x27RP 0x0101 GDT6127RP/GDT6527RP
+product VORTEX GDT_6537RP 0x0102 GDT6537RP
+product VORTEX GDT_6557RP 0x0103 GDT6557RP
+/* GDT_MPR, RP series, narrow/ultra SCSI */
+product VORTEX GDT_6x11RP 0x0104 GDT6111RP/GDT6511RP
+product VORTEX GDT_6x21RP 0x0105 GDT6121RP/GDT6521RP
+/* GDT_MPR, RD series, wide/ultra SCSI */
+product VORTEX GDT_6x17RD 0x0110 GDT6117RD/GDT6517RD
+product VORTEX GDT_6x27RD 0x0111 GDT6127RD/GDT6527RD
+product VORTEX GDT_6537RD 0x0112 GDT6537RD
+product VORTEX GDT_6557RD 0x0113 GDT6557RD
+/* GDT_MPR, RD series, narrow/ultra SCSI */
+product VORTEX GDT_6x11RD 0x0114 GDT6111RD/GDT6511RD
+product VORTEX GDT_6x21RD 0x0115 GDT6121RD/GDT6521RD
+/* GDT_MPR, RD series, wide/ultra2 SCSI */
+product VORTEX GDT_6x18RD 0x0118 GDT6118RD/GDT6518RD/GDT6618RD
+product VORTEX GDT_6x28RD 0x0119 GDT6128RD/GDT6528RD/GDT6628RD
+product VORTEX GDT_6x38RD 0x011A GDT6538RD/GDT6638RD
+product VORTEX GDT_6x58RD 0x011B GDT6558RD/GDT6658RD
+/* GDT_MPR, RN series (64-bit PCI), wide/ultra2 SCSI */
+product VORTEX GDT_7x18RN 0x0168 GDT7118RN/GDT7518RN/GDT7618RN
+product VORTEX GDT_7x28RN 0x0169 GDT7128RN/GDT7528RN/GDT7628RN
+product VORTEX GDT_7x38RN 0x016A GDT7538RN/GDT7638RN
+product VORTEX GDT_7x58RN 0x016B GDT7558RN/GDT7658RN
+/* GDT_MPR, RD series, Fibre Channel */
+product VORTEX GDT_6x19RD 0x0210 GDT6519RD/GDT6619RD
+product VORTEX GDT_6x29RD 0x0211 GDT6529RD/GDT6629RD
+/* GDT_MPR, RN series (64-bit PCI), Fibre Channel */
+product VORTEX GDT_7x19RN 0x0260 GDT7519RN/GDT7619RN
+product VORTEX GDT_7x29RN 0x0261 GDT7529RN/GDT7629RN
+
+/* VLSI products */
+product VLSI 82C592 0x0005 82C592 CPU Bridge
+product VLSI 82C593 0x0006 82C593 ISA Bridge
+product VLSI 82C594 0x0007 82C594 Wildcat System Controller
+product VLSI 82C596597 0x0008 82C596/597 Wildcat ISA Bridge
+product VLSI 82C541 0x000c 82C541
+product VLSI 82C543 0x000d 82C543
+product VLSI 82C532 0x0101 82C532
+product VLSI 82C534 0x0102 82C534
+product VLSI 82C535 0x0104 82C535
+product VLSI 82C147 0x0105 82C147
+product VLSI 82C975 0x0200 82C975
+product VLSI 82C925 0x0280 82C925
+
+/* Weitek products */
+product WEITEK P9000 0x9001 P9000
+product WEITEK P9100 0x9100 P9100
+
+/* Western Digital products */
+product WD WD33C193A 0x0193 WD33C193A
+product WD WD33C196A 0x0196 WD33C196A
+product WD WD33C197A 0x0197 WD33C197A
+product WD WD7193 0x3193 WD7193
+product WD WD7197 0x3197 WD7197
+product WD WD33C296A 0x3296 WD33C296A
+product WD WD34C296 0x4296 WD34C296
+product WD 90C 0xC24A 90C
+
+/* Winbond Electronics products */
+product WINBOND W83769F 0x0001 W83769F
+product WINBOND W89C840F 0x0840 W89C840F 10/100 Ethernet
+product WINBOND W89C940F 0x0940 W89C940F Ethernet
+product WINBOND W89C940F_1 0x5a5a W89C940F Ethernet
+
+/* Xircom products */
+/* is the `-3' here just indicating revision 3, or is it really part
+ of the device name? */
+product XIRCOM X3201_3 0x0002 X3201-3 Fast Ethernet Controller
+/* this is the device id `indicating 21143 driver compatibility' */
+product XIRCOM X3201_3_21143 0x0003 X3201-3 Fast Ethernet Controller (21143)
+
+/* Yamaha products */
+product YAMAHA YMF724 0x0004 724 Audio
+product YAMAHA YMF740 0x000A 740 Audio
+product YAMAHA YMF740C 0x000C 740C (DS-1) Audio
+product YAMAHA YMF724F 0x000D 724F (DS-1) Audio
+product YAMAHA YMF744B 0x0010 744 (DS-1S) Audio
+product YAMAHA YMF754 0x0012 754 (DS-1E) Audio
+
+/* Zeinet products */
+product ZEINET 1221 0x0001 1221
+
+/* Ziatech products */
+product ZIATECH ZT8905 0x8905 PCI-ST32 Bridge
+
+/* Zoran products */
+product ZORAN ZR36120 0x6120 Video Controller
diff --git a/cfe/cfe/pci/pcidevs.h b/cfe/cfe/pci/pcidevs.h
new file mode 100644
index 0000000..214ef45
--- /dev/null
+++ b/cfe/cfe/pci/pcidevs.h
@@ -0,0 +1,1360 @@
+/*
+ * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.
+ *
+ * generated from:
+ * pcidevs 2002/09/03 broadcom
+ */
+
+/*
+ * Copyright (c) 1995, 1996 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * NOTE: a fairly complete list of PCI codes can be found at:
+ *
+ * http://members.hyperlink.net.au/~chart/pci.htm
+ *
+ * which replaces the database found at
+ *
+ * http://www.yourvote.com/pci/
+ *
+ * (but it doesn't always seem to match vendor documentation)
+ */
+
+/*
+ * List of known PCI vendors. This list has been trimmed to include
+ * only vendors with products appearing in the lists below.
+ */
+
+#define PCI_VENDOR_COMPAQ 0x0e11 /* Compaq */
+#define PCI_VENDOR_SYMBIOS 0x1000 /* Symbios Logic */
+#define PCI_VENDOR_ATI 0x1002 /* ATI Technologies */
+#define PCI_VENDOR_ULSI 0x1003 /* ULSI Systems */
+#define PCI_VENDOR_VLSI 0x1004 /* VLSI Technology */
+#define PCI_VENDOR_AVANCE 0x1005 /* Avance Logic */
+#define PCI_VENDOR_NS 0x100b /* National Semiconductor */
+#define PCI_VENDOR_TSENG 0x100c /* Tseng Labs */
+#define PCI_VENDOR_WEITEK 0x100e /* Weitek */
+#define PCI_VENDOR_DEC 0x1011 /* Digital Equipment */
+#define PCI_VENDOR_CIRRUS 0x1013 /* Cirrus Logic */
+#define PCI_VENDOR_IBM 0x1014 /* IBM */
+#define PCI_VENDOR_WD 0x101c /* Western Digital */
+#define PCI_VENDOR_AMD 0x1022 /* Advanced Micro Devices */
+#define PCI_VENDOR_TRIDENT 0x1023 /* Trident Microsystems */
+#define PCI_VENDOR_ACER 0x1025 /* Acer */
+#define PCI_VENDOR_MATROX 0x102b /* Matrox */
+#define PCI_VENDOR_CHIPS 0x102c /* Chips and Technologies */
+#define PCI_VENDOR_TOSHIBA 0x102f /* Toshiba America */
+#define PCI_VENDOR_NEC 0x1033 /* NEC */
+#define PCI_VENDOR_FUTUREDOMAIN 0x1036 /* Future Domain */
+#define PCI_VENDOR_SIS 0x1039 /* Silicon Integrated System */
+#define PCI_VENDOR_HP 0x103c /* Hewlett-Packard */
+#define PCI_VENDOR_PCTECH 0x1042 /* PC Technology */
+#define PCI_VENDOR_DPT 0x1044 /* Distributed Processing Technology */
+#define PCI_VENDOR_OPTI 0x1045 /* Opti */
+#define PCI_VENDOR_ELSA 0x1048 /* Elsa */
+#define PCI_VENDOR_SGSTHOMSON 0x104a /* SGS Thomson Microelectric */
+#define PCI_VENDOR_BUSLOGIC 0x104b /* BusLogic */
+#define PCI_VENDOR_TI 0x104c /* Texas Instruments */
+#define PCI_VENDOR_SONY 0x104d /* Sony */
+#define PCI_VENDOR_OAKTECH 0x104e /* Oak Technology */
+#define PCI_VENDOR_WINBOND 0x1050 /* Winbond Electronics */
+#define PCI_VENDOR_MOT 0x1057 /* Motorola */
+#define PCI_VENDOR_PROMISE 0x105a /* Promise Technology */
+#define PCI_VENDOR_NUMBER9 0x105d /* Number 9 Computer Company */
+#define PCI_VENDOR_UMC 0x1060 /* United Microelectronics */
+#define PCI_VENDOR_ITT 0x1061 /* I. T. T. */
+#define PCI_VENDOR_MYLEX 0x1069 /* Mylex */
+#define PCI_VENDOR_APPLE 0x106b /* Apple Computer */
+#define PCI_VENDOR_YAMAHA 0x1073 /* Yamaha */
+#define PCI_VENDOR_NEXGEN 0x1074 /* NexGen Microsystems */
+#define PCI_VENDOR_QLOGIC 0x1077 /* Q Logic */
+#define PCI_VENDOR_LEADTEK 0x107d /* LeadTek Research */
+#define PCI_VENDOR_CONTAQ 0x1080 /* Contaq Microsystems */
+#define PCI_VENDOR_BIT3 0x108a /* Bit3 Computer Corp. */
+#define PCI_VENDOR_OLICOM 0x108d /* Olicom */
+#define PCI_VENDOR_SUN 0x108e /* Sun Microsystems */
+#define PCI_VENDOR_INTERGRAPH 0x1091 /* Intergraph */
+#define PCI_VENDOR_DIAMOND 0x1092 /* Diamond Computer Systems */
+#define PCI_VENDOR_CMDTECH 0x1095 /* CMD Technology */
+#define PCI_VENDOR_QUANTUMDESIGNS 0x1098 /* Quantum Designs */
+#define PCI_VENDOR_BROOKTREE 0x109e /* Brooktree */
+#define PCI_VENDOR_SGI 0x10a9 /* Silicon Graphics */
+#define PCI_VENDOR_ACC 0x10aa /* ACC Microelectronics */
+#define PCI_VENDOR_SYMPHONY 0x10ad /* Symphony Labs */
+#define PCI_VENDOR_PLX 0x10b5 /* PLX Technology */
+#define PCI_VENDOR_MADGE 0x10b6 /* Madge Networks */
+#define PCI_VENDOR_3COM 0x10B7 /* 3Com */
+#define PCI_VENDOR_SMC 0x10b8 /* Standard Microsystems */
+#define PCI_VENDOR_ALI 0x10b9 /* Acer Labs */
+#define PCI_VENDOR_SURECOM 0x10bd /* Surecom Technology */
+#define PCI_VENDOR_SAMSUNGSEMI 0x10c3 /* Samsung Semiconductors */
+#define PCI_VENDOR_NEOMAGIC 0x10c8 /* Neomagic */
+#define PCI_VENDOR_ADVSYS 0x10cd /* Advanced System Products */
+#define PCI_VENDOR_MACRONIX 0x10d9 /* Macronix */
+#define PCI_VENDOR_ES 0x10dd /* Evans & Sutherland */
+#define PCI_VENDOR_NVIDIA 0x10de /* Nvidia Corporation */
+#define PCI_VENDOR_EMULEX 0x10df /* Emulex */
+#define PCI_VENDOR_IMS 0x10e0 /* Integrated Micro Solutions */
+#define PCI_VENDOR_TEKRAM 0x10e1 /* Tekram Technology (1st PCI Vendor ID) */
+#define PCI_VENDOR_NEWBRIDGE 0x10e3 /* Newbridge Microsystems / Tundra Semiconductor */
+#define PCI_VENDOR_AMCIRCUITS 0x10e8 /* Applied Micro Circuits */
+#define PCI_VENDOR_REALTEK 0x10ec /* Realtek Semiconductor */
+#define PCI_VENDOR_NKK 0x10f5 /* NKK Corporation */
+#define PCI_VENDOR_INITIO 0x1101 /* Initio */
+#define PCI_VENDOR_CREATIVELABS 0x1102 /* Creative Labs */
+#define PCI_VENDOR_TRIONES 0x1103 /* Triones Technologies */
+#define PCI_VENDOR_SIGMA 0x1105 /* Sigma Designs */
+#define PCI_VENDOR_VIATECH 0x1106 /* VIA Technologies */
+#define PCI_VENDOR_COGENT 0x1109 /* Cogent Data Technologies */
+#define PCI_VENDOR_RNS 0x1112 /* RNS */
+#define PCI_VENDOR_ACCTON 0x1113 /* Accton Technology */
+#define PCI_VENDOR_VORTEX 0x1119 /* Vortex Computer Systems */
+#define PCI_VENDOR_EFFICIENTNETS 0x111a /* Efficent Networks */
+#define PCI_VENDOR_IDT 0x111d /* IDT */
+#define PCI_VENDOR_FORE 0x1127 /* FORE Systems */
+#define PCI_VENDOR_ZIATECH 0x1138 /* Ziatech */
+#define PCI_VENDOR_ALLIANCE 0x1142 /* Alliance Semiconductor */
+#define PCI_VENDOR_SCHNEIDERKOCH 0x1148 /* Schneider & Koch */
+#define PCI_VENDOR_MUTECH 0x1159 /* Mutech */
+#define PCI_VENDOR_XIRCOM 0x115d /* Xircom */
+#define PCI_VENDOR_ALTERA 0x1172 /* Altera Corporation */
+#define PCI_VENDOR_TOSHIBA2 0x1179 /* Toshiba America Info Systems */
+#define PCI_VENDOR_RICOH 0x1180 /* Ricoh */
+#define PCI_VENDOR_DLINK 0x1186 /* D-Link Systems */
+#define PCI_VENDOR_COROLLARY 0x118c /* Corrollary */
+#define PCI_VENDOR_ACARD 0x1191 /* Acard */
+#define PCI_VENDOR_ZEINET 0x1193 /* Zeinet */
+#define PCI_VENDOR_GALILEO 0x11ab /* Galileo Technology */
+#define PCI_VENDOR_LITEON 0x11ad /* Lite-On Communications */
+#define PCI_VENDOR_V3 0x11b0 /* V3 Semiconductor */
+#define PCI_VENDOR_LUCENT 0x11c1 /* AT&T Microelectronics */
+#define PCI_VENDOR_DOLPHIN 0x11c8 /* Dolphin Interconnect Solutions */
+#define PCI_VENDOR_AURAVISION 0x11d1 /* Auravision */
+#define PCI_VENDOR_ZORAN 0x11de /* Zoran Corporation */
+#define PCI_VENDOR_COMPEX 0x11f6 /* Compex */
+#define PCI_VENDOR_PMCSIERRA 0x11f8 /* PMC-Sierra */
+#define PCI_VENDOR_CYCLADES 0x120e /* Cyclades */
+#define PCI_VENDOR_ESSENTIAL 0x120f /* Essential Communications */
+#define PCI_VENDOR_O2MICRO 0x1217 /* O2 Micro Inc */
+#define PCI_VENDOR_3DFX 0x121a /* 3Dfx Interactive */
+#define PCI_VENDOR_CCUBE 0x123f /* C-Cube Microsystems */
+#define PCI_VENDOR_AVM 0x1244 /* AVM */
+#define PCI_VENDOR_LINEARSYS 0x1254 /* Linear Systems */
+#define PCI_VENDOR_ASIX 0x125b /* ASIX Electronics */
+#define PCI_VENDOR_ESSTECH 0x125d /* ESS Technology Inc */
+#define PCI_VENDOR_SILMOTION 0x126f /* Silicon Motion */
+#define PCI_VENDOR_ENSONIQ 0x1274 /* Ensoniq */
+#define PCI_VENDOR_DAVICOM 0x1282 /* Davicom Semiconductor */
+#define PCI_VENDOR_ESSTECH2 0x1285 /* ESS Technology Inc */
+#define PCI_VENDOR_TRITECH 0x1292 /* TriTech Microelectronics */
+#define PCI_VENDOR_ALTEON 0x12ae /* Alteon */
+#define PCI_VENDOR_RISCOM 0x12aa /* RISCom */
+#define PCI_VENDOR_USR 0x12b9 /* US Robotics (3Com) */
+#define PCI_VENDOR_NVIDIA_SGS 0x12d2 /* Nvidia Corporation & SGS Thomson Microelectric */
+#define PCI_VENDOR_AUREAL 0x12eb /* Aureal Semiconductor */
+#define PCI_VENDOR_ADMTEK 0x1317 /* ADMtek */
+#define PCI_VENDOR_FORTEMEDIA 0x1319 /* Forte Media */
+#define PCI_VENDOR_DOMEX 0x134a /* Domex */
+#define PCI_VENDOR_LMC 0x1376 /* LAN Media Corporation */
+#define PCI_VENDOR_API 0x14d9 /* API Networks */
+#define PCI_VENDOR_CONEXANT 0x14f1 /* Conexant Systems */
+#define PCI_VENDOR_NETGEAR 0x1385 /* Netgear */
+#define PCI_VENDOR_3WARE 0x13c1 /* 3ware */
+#define PCI_VENDOR_SUNDANCETI 0x13f0 /* Sundance Technology */
+#define PCI_VENDOR_CMEDIA 0x13f6 /* C-Media Electronics Inc */
+#define PCI_VENDOR_DELTA 0x1500 /* Delta Electronics */
+#define PCI_VENDOR_SOLIDUM 0x1588 /* Solidum Systems Corp. */
+#define PCI_VENDOR_SIBYTE 0x166d /* SiByte, Inc. */
+#define PCI_VENDOR_SYMPHONY2 0x1c1c /* Symphony Labs (2nd PCI Vendor ID) */
+#define PCI_VENDOR_TEKRAM2 0x1de1 /* Tekram Technology (2nd PCI Vendor ID) */
+#define PCI_VENDOR_BROADCOM 0x14e4 /* Broadcom */
+#define PCI_VENDOR_3DLABS 0x3d3d /* 3D Labs */
+#define PCI_VENDOR_AVANCE2 0x4005 /* Avance Logic (2nd PCI Vendor ID) */
+#define PCI_VENDOR_ADDTRON 0x4033 /* Addtron Technology */
+#define PCI_VENDOR_NETVIN 0x4a14 /* NetVin */
+#define PCI_VENDOR_S3 0x5333 /* S3 */
+#define PCI_VENDOR_C4T 0x6374 /* c't Magazin */
+#define PCI_VENDOR_INTEL 0x8086 /* Intel */
+#define PCI_VENDOR_PROLAN 0x8c4a /* ProLAN */
+#define PCI_VENDOR_KTI 0x8e2e /* KTI */
+#define PCI_VENDOR_ADP 0x9004 /* Adaptec */
+#define PCI_VENDOR_ADP2 0x9005 /* Adaptec (2nd PCI Vendor ID) */
+#define PCI_VENDOR_ATRONICS 0x907f /* Atronics */
+#define PCI_VENDOR_ARC 0xedd8 /* ARC Logic */
+#define PCI_VENDOR_EPIGRAM 0xfeda /* Epigram */
+#define PCI_VENDOR_INVALID 0xffff /* INVALID VENDOR ID */
+
+/*
+ * List of known products. Grouped by vendor.
+ */
+
+/* 3COM Products */
+#define PCI_PRODUCT_3COM_3C985 0x0001 /* 3c985 Gigabit Ethernet */
+#define PCI_PRODUCT_3COM_3C590 0x5900 /* 3c590 Ethernet */
+#define PCI_PRODUCT_3COM_3C595TX 0x5950 /* 3c595-TX 10/100 Ethernet */
+#define PCI_PRODUCT_3COM_3C595T4 0x5951 /* 3c595-T4 10/100 Ethernet */
+#define PCI_PRODUCT_3COM_3C595MII 0x5952 /* 3c595-MII 10/100 Ethernet */
+#define PCI_PRODUCT_3COM_3C900TPO 0x9000 /* 3c900-TPO Ethernet */
+#define PCI_PRODUCT_3COM_3C900COMBO 0x9001 /* 3c900-COMBO Ethernet */
+#define PCI_PRODUCT_3COM_3C905TX 0x9050 /* 3c905-TX 10/100 Ethernet */
+#define PCI_PRODUCT_3COM_3C905T4 0x9051 /* 3c905-T4 10/100 Ethernet */
+#define PCI_PRODUCT_3COM_3C900BTPO 0x9004 /* 3c900B-TPO Ethernet */
+#define PCI_PRODUCT_3COM_3C900BCOMBO 0x9005 /* 3c900B-COMBO Ethernet */
+#define PCI_PRODUCT_3COM_3C900BTPC 0x9006 /* 3c900B-TPC Ethernet */
+#define PCI_PRODUCT_3COM_3C905BTX 0x9055 /* 3c905B-TX 10/100 Ethernet */
+#define PCI_PRODUCT_3COM_3C905BT4 0x9056 /* 3c905B-T4 10/100 Ethernet */
+#define PCI_PRODUCT_3COM_3C905BCOMBO 0x9058 /* 3c905B-COMBO 10/100 Ethernet */
+#define PCI_PRODUCT_3COM_3C905BFX 0x905a /* 3c905B-FX 100 Ethernet */
+#define PCI_PRODUCT_3COM_3C905CTX 0x9200 /* 3c905C-TX 10/100 Ethernet with mngmt */
+#define PCI_PRODUCT_3COM_3C980SRV 0x9800 /* 3c980 Server Adapter 10/100 Ethernet */
+#define PCI_PRODUCT_3COM_3C980CTXM 0x9805 /* 3c980C-TXM 10/100 Ethernet */
+#define PCI_PRODUCT_3COM_3CR990TX97 0x9903 /* 3CR990-TX-97 10/100 Ethernet */
+
+/* 3Dfx Interactive producs */
+#define PCI_PRODUCT_3DFX_VOODOO 0x0001 /* Voodoo */
+#define PCI_PRODUCT_3DFX_VOODOO2 0x0002 /* Voodoo2 */
+#define PCI_PRODUCT_3DFX_BANSHEE 0x0003 /* Banshee */
+#define PCI_PRODUCT_3DFX_VOODOO3 0x0005 /* Voodoo3 */
+
+/* 3D Labs products */
+#define PCI_PRODUCT_3DLABS_300SX 0x0001 /* GLINT 300SX */
+#define PCI_PRODUCT_3DLABS_500TX 0x0002 /* GLINT 500TX */
+#define PCI_PRODUCT_3DLABS_DELTA 0x0003 /* GLINT DELTA */
+#define PCI_PRODUCT_3DLABS_PERMEDIA 0x0004 /* GLINT Permedia */
+#define PCI_PRODUCT_3DLABS_500MX 0x0006 /* GLINT 500MX */
+#define PCI_PRODUCT_3DLABS_PERMEDI2 0x0007 /* GLINT Permedia 2 */
+
+/* 3ware products */
+#define PCI_PRODUCT_3WARE_ESCALADE 0x1000 /* Escalade IDE RAID */
+
+/* ACC Products */
+#define PCI_PRODUCT_ACC_2188 0x0000 /* ACCM 2188 VL-PCI Bridge */
+#define PCI_PRODUCT_ACC_2051_HB 0x2051 /* 2051 PCI Single Chip Solution (host bridge) */
+#define PCI_PRODUCT_ACC_2051_ISA 0x5842 /* 2051 PCI Single Chip Solution (ISA bridge) */
+
+/* Acard products */
+#define PCI_PRODUCT_ACARD_AEC6710 0x8002 /* AEC6710 SCSI */
+#define PCI_PRODUCT_ACARD_AEC6712UW 0x8010 /* AEC6712UW SCSI */
+#define PCI_PRODUCT_ACARD_AEC6712U 0x8020 /* AEC6712U SCSI */
+#define PCI_PRODUCT_ACARD_AEC6712S 0x8030 /* AEC6712S SCSI */
+#define PCI_PRODUCT_ACARD_AEC6710D 0x8040 /* AEC6710D SCSI */
+#define PCI_PRODUCT_ACARD_AEC6715UW 0x8050 /* AEC6715UW SCSI */
+
+/* Accton products */
+#define PCI_PRODUCT_ACCTON_MPX5030 0x1211 /* MPX 5030/5038 Ethernet */
+
+/* Acer products */
+#define PCI_PRODUCT_ACER_M1435 0x1435 /* M1435 VL-PCI Bridge */
+
+/* Acer Labs products */
+#define PCI_PRODUCT_ALI_M1445 0x1445 /* M1445 VL-PCI Bridge */
+#define PCI_PRODUCT_ALI_M1449 0x1449 /* M1449 PCI-ISA Bridge */
+#define PCI_PRODUCT_ALI_M1451 0x1451 /* M1451 Host-PCI Bridge */
+#define PCI_PRODUCT_ALI_M1461 0x1461 /* M1461 Host-PCI Bridge */
+#define PCI_PRODUCT_ALI_M1531 0x1531 /* M1531 Host-PCI Bridge */
+#define PCI_PRODUCT_ALI_M1541 0x1541 /* M1541 Host-PCI Bridge */
+#define PCI_PRODUCT_ALI_M1543 0x1533 /* M1543 PCI-ISA Bridge */
+#define PCI_PRODUCT_ALI_M3309 0x3309 /* M3309 MPEG Decoder */
+#define PCI_PRODUCT_ALI_M4803 0x5215 /* M4803 */
+#define PCI_PRODUCT_ALI_M5229 0x5229 /* M5229 UDMA IDE Controller */
+#define PCI_PRODUCT_ALI_M5237 0x5237 /* M5237 USB Host Controller */
+#define PCI_PRODUCT_ALI_M7101 0x7101 /* M7101 Power Management Controller */
+
+/* Adaptec products */
+#define PCI_PRODUCT_ADP_AIC7850 0x5078 /* AIC-7850 */
+#define PCI_PRODUCT_ADP_AIC7855 0x5578 /* AIC-7855 */
+#define PCI_PRODUCT_ADP_AIC5900 0x5900 /* AIC-5900 ATM */
+#define PCI_PRODUCT_ADP_AIC5905 0x5905 /* AIC-5905 ATM */
+#define PCI_PRODUCT_ADP_AIC6915 0x6915 /* AIC-6915 10/100 Ethernet */
+#define PCI_PRODUCT_ADP_AIC7860 0x6078 /* AIC-7860 */
+#define PCI_PRODUCT_ADP_APA1480 0x6075 /* APA-1480 Ultra */
+#define PCI_PRODUCT_ADP_2940AU 0x6178 /* AHA-2940A Ultra */
+#define PCI_PRODUCT_ADP_AIC7870 0x7078 /* AIC-7870 */
+#define PCI_PRODUCT_ADP_2940 0x7178 /* AHA-2940 */
+#define PCI_PRODUCT_ADP_3940 0x7278 /* AHA-3940 */
+#define PCI_PRODUCT_ADP_3985 0x7378 /* AHA-3985 */
+#define PCI_PRODUCT_ADP_2944 0x7478 /* AHA-2944 */
+#define PCI_PRODUCT_ADP_AIC7895 0x7895 /* AIC-7895 Ultra */
+#define PCI_PRODUCT_ADP_AIC7880 0x8078 /* AIC-7880 Ultra */
+#define PCI_PRODUCT_ADP_2940U 0x8178 /* AHA-2940 Ultra */
+#define PCI_PRODUCT_ADP_3940U 0x8278 /* AHA-3940 Ultra */
+#define PCI_PRODUCT_ADP_389XU 0x8378 /* AHA-389X Ultra */
+#define PCI_PRODUCT_ADP_2944U 0x8478 /* AHA-2944 Ultra */
+#define PCI_PRODUCT_ADP_2940UP 0x8778 /* AHA-2940 Ultra Pro */
+
+#define PCI_PRODUCT_ADP2_2940U2 0x0010 /* AHA-2940 Ultra2 */
+#define PCI_PRODUCT_ADP2_2930U2 0x0011 /* AHA-2930 Ultra2 */
+#define PCI_PRODUCT_ADP2_AIC7890 0x001f /* AIC-7890/1 */
+#define PCI_PRODUCT_ADP2_3950U2B 0x0050 /* AHA-3950 Ultra2 */
+#define PCI_PRODUCT_ADP2_3950U2D 0x0051 /* AHA-3950 Ultra2 */
+#define PCI_PRODUCT_ADP2_AIC7896 0x005f /* AIC-7896/7 */
+
+/* Addtron Products */
+#define PCI_PRODUCT_ADDTRON_8139 0x1360 /* 8139 Ethernet */
+
+/* ADMtek products */
+#define PCI_PRODUCT_ADMTEK_AL981 0x0981 /* ADMtek AL981 10/100 Ethernet */
+
+/* Advanced System Products */
+#define PCI_PRODUCT_ADVSYS_1200A 0x1100
+#define PCI_PRODUCT_ADVSYS_1200B 0x1200
+#define PCI_PRODUCT_ADVSYS_ULTRA 0x1300 /* ABP-930/40UA */
+#define PCI_PRODUCT_ADVSYS_WIDE 0x2300 /* ABP-940UW */
+#define PCI_PRODUCT_ADVSYS_U2W 0x2500 /* ASB-3940U2W */
+#define PCI_PRODUCT_ADVSYS_U3W 0x2700 /* ASB-3940U3W */
+
+/* Alliance products */
+#define PCI_PRODUCT_ALLIANCE_AT24 0x6424 /* AT24 */
+#define PCI_PRODUCT_ALLIANCE_AT25 0x643d /* AT25 */
+
+/* Alteon products */
+#define PCI_PRODUCT_ALTEON_ACENIC 0x0001 /* ACEnic Gigabit Ethernet */
+
+/* AMD products */
+#define PCI_PRODUCT_AMD_PCNET_PCI 0x2000 /* 79c970 PCnet-PCI LANCE Ethernet */
+#define PCI_PRODUCT_AMD_PCNET_HOME 0x2001 /* 79c978 PCnet-PCI Home */
+#define PCI_PRODUCT_AMD_PCSCSI_PCI 0x2020 /* 53c974 PCscsi-PCI SCSI */
+#define PCI_PRODUCT_AMD_PCNETS_PCI 0x2040 /* 79C974 PCnet-PCI Ethernet & SCSI */
+#define PCI_PRODUCT_AMD_SC751_SC 0x7006 /* AMD751 System Controller */
+#define PCI_PRODUCT_AMD_SC751_PPB 0x7007 /* AMD751 PCI-to-PCI Bridge */
+#define PCI_PRODUCT_AMD_PBC756_ISA 0x7408 /* AMD756 PCI-to-ISA Bridge */
+#define PCI_PRODUCT_AMD_PBC756_IDE 0x7409 /* AMD756 IDE controller */
+#define PCI_PRODUCT_AMD_PBC756_PMC 0x740B /* AMD756 Power Management Controller */
+#define PCI_PRODUCT_AMD_PBC756_USB 0x740C /* AMD756 USB Host Controller */
+#define PCI_PRODUCT_AMD_HT7520 0x7450 /* (PLX) HT7520 PCIX Tunnel */
+#define PCI_PRODUCT_AMD_HT7520_PIC 0x7451 /* (PLX) HT7520 PCIX IOAPIC */
+#define PCI_PRODUCT_AMD_AMD8151_AGP 0x7454 /* AMD8151 AGP Device */
+#define PCI_PRODUCT_AMD_AMD8151 0x7455 /* AMD8151 HyperTransport-AGP Bridge */
+
+/* API Networks products */
+#define PCI_PRODUCT_API_STURGEON 0x0010 /* AP1011 HyperTransport-PCI Bridge */
+
+/* Apple products */
+#define PCI_PRODUCT_APPLE_BANDIT 0x0001 /* Bandit Host-PCI Bridge */
+#define PCI_PRODUCT_APPLE_GC 0x0002 /* Grand Central I/O Controller */
+#define PCI_PRODUCT_APPLE_CONTROL 0x0003 /* Control */
+#define PCI_PRODUCT_APPLE_PLANB 0x0004 /* PlanB */
+#define PCI_PRODUCT_APPLE_OHARE 0x0007 /* OHare I/O Controller */
+#define PCI_PRODUCT_APPLE_BANDIT2 0x0008 /* Bandit Host-PCI Bridge */
+#define PCI_PRODUCT_APPLE_HEATHROW 0x0010 /* MAC-IO I/O Controller (Heathrow) */
+#define PCI_PRODUCT_APPLE_PADDINGTON 0x0017 /* MAC-IO I/O Controller (Paddington) */
+#define PCI_PRODUCT_APPLE_KEYLARGO_USB 0x0019 /* KeyLargo USB Controller */
+#define PCI_PRODUCT_APPLE_UNINORTH1 0x001e /* UniNorth Host-PCI Bridge */
+#define PCI_PRODUCT_APPLE_UNINORTH2 0x001f /* UniNorth Host-PCI Bridge */
+#define PCI_PRODUCT_APPLE_UNINORTH_AGP 0x0020 /* UniNorth AGP Interface */
+#define PCI_PRODUCT_APPLE_GMAC 0x0021 /* GMAC Ethernet */
+#define PCI_PRODUCT_APPLE_KEYLARGO 0x0022 /* MAC-IO I/O Controller (KeyLargo) */
+
+/* ARC Logic products */
+#define PCI_PRODUCT_ARC_1000PV 0xa091 /* 1000PV */
+#define PCI_PRODUCT_ARC_2000PV 0xa099 /* 2000PV */
+#define PCI_PRODUCT_ARC_2000MT 0xa0a1 /* 2000MT */
+
+/* ASIX Electronics products */
+#define PCI_PRODUCT_ASIX_AX88140A 0x1400 /* AX88140A 10/100 Ethernet */
+
+/* ATI products */
+#define PCI_PRODUCT_ATI_MACH32 0x4158 /* Mach32 */
+#define PCI_PRODUCT_ATI_MACH64_CT 0x4354 /* Mach64 CT */
+#define PCI_PRODUCT_ATI_MACH64_CX 0x4358 /* Mach64 CX */
+#define PCI_PRODUCT_ATI_MACH64_ET 0x4554 /* Mach64 ET */
+#define PCI_PRODUCT_ATI_MACH64_VT 0x4654 /* Mach64 VT */
+#define PCI_PRODUCT_ATI_MACH64_B 0x4750 /* Mach64 B */
+#define PCI_PRODUCT_ATI_MACH64_GB 0x4742 /* Mach64 GB */
+#define PCI_PRODUCT_ATI_MACH64_GD 0x4744 /* Mach64 GD */
+#define PCI_PRODUCT_ATI_MACH64_GI 0x4749 /* Mach64 GI */
+#define PCI_PRODUCT_ATI_MACH64_GP 0x4750 /* Mach64 GP */
+#define PCI_PRODUCT_ATI_MACH64_GQ 0x4751 /* Mach64 GQ */
+#define PCI_PRODUCT_ATI_MACH64_GT 0x4754 /* Mach64 GT */
+#define PCI_PRODUCT_ATI_MACH64_GU 0x4755 /* Mach64 GU */
+#define PCI_PRODUCT_ATI_MACH64_GV 0x4756 /* Mach64 GV */
+#define PCI_PRODUCT_ATI_MACH64_GW 0x4757 /* Mach64 GW */
+#define PCI_PRODUCT_ATI_MACH64_GX 0x4758 /* Mach64 GX */
+#define PCI_PRODUCT_ATI_MACH64_GZ 0x475a /* Mach64 GZ */
+#define PCI_PRODUCT_ATI_MACH64_LB 0x4c42 /* Mach64 LB */
+#define PCI_PRODUCT_ATI_MACH64_LD 0x4c44 /* Mach64 LD */
+#define PCI_PRODUCT_ATI_MACH64_LG 0x4c47 /* Mach64 LG */
+#define PCI_PRODUCT_ATI_MACH64_LI 0x4c49 /* Mach64 LI */
+#define PCI_PRODUCT_ATI_MACH64_LM 0x4c4d /* Mach64 LM */
+#define PCI_PRODUCT_ATI_MACH64_LP 0x4c50 /* Mach64 LP */
+#define PCI_PRODUCT_ATI_MACH64_LR 0x4c52 /* Mach64 LR */
+
+/* Auravision products */
+#define PCI_PRODUCT_AURAVISION_VXP524 0x01f7 /* VxP524 PCI Video Processor */
+
+/* Aureal Semiconductor */
+#define PCI_PRODUCT_AUREAL_AU8820 0x0001 /* AU8820 Vortex Digital Audio Processor */
+
+/* Applied Micro Circuts products */
+#define PCI_PRODUCT_AMCIRCUITS_S5933 0x4750 /* S5933 PCI Matchmaker */
+#define PCI_PRODUCT_AMCIRCUITS_LANAI 0x8043 /* Myrinet LANai Interface */
+#define PCI_PRODUCT_AMCIRCUITS_S5920 0x5920 /* S5920 PCI Target */
+
+/* Atronics products */
+#define PCI_PRODUCT_ATRONICS_IDE_2015PL 0x2015 /* IDE-2015PL */
+
+/* Avance Logic products */
+#define PCI_PRODUCT_AVANCE_AVL2301 0x2301 /* AVL2301 */
+#define PCI_PRODUCT_AVANCE_AVG2302 0x2302 /* AVG2302 */
+#define PCI_PRODUCT_AVANCE2_ALG2301 0x2301 /* ALG2301 */
+#define PCI_PRODUCT_AVANCE2_ALG2302 0x2302 /* ALG2302 */
+
+/* CCUBE products */
+#define PCI_PRODUCT_CCUBE_CINEMASTER 0x8888 /* Cinemaster C 3.0 DVD Decoder */
+
+/* AVM products */
+#define PCI_PRODUCT_AVM_FRITZ_CARD 0x0a00 /* Fritz! Card ISDN Interface */
+
+/* Bit3 products */
+#define PCI_PRODUCT_BIT3_PCIVME617 0x0001 /* PCI-VME Interface Mod. 617 */
+#define PCI_PRODUCT_BIT3_PCIVME618 0x0010 /* PCI-VME Interface Mod. 618 */
+#define PCI_PRODUCT_BIT3_PCIVME2706 0x0300 /* PCI-VME Interface Mod. 2706 */
+
+/* Broadcom products */
+#define PCI_PRODUCT_BROADCOM_BCM4211 0x4211 /* BCM4211 iLine10 Controller */
+#define PCI_PRODUCT_BROADCOM_BCM4212 0x4212 /* BCM4212 V.90 Modem */
+#define PCI_PRODUCT_BROADCOM_BCM5700 0x1644 /* BCM5700 10/100/1000 Ethernet */
+#define PCI_PRODUCT_BROADCOM_BCM5701 0x1645 /* BCM5701 10/100/1000 Ethernet */
+#define PCI_PRODUCT_BROADCOM_BCM5702 0x16a6 /* BCM5702 10/100/1000 Ethernet */
+#define PCI_PRODUCT_BROADCOM_BCM5703 0x16a7 /* BCM5703 10/100/1000 Ethernet */
+#define PCI_PRODUCT_BROADCOM_BCM5705 0x1653 /* BCM5705 10/100/1000 Ethernet */
+#define PCI_PRODUCT_BROADCOM_BCM5820 0x5820 /* BCM5820 eCommerce Processor */
+#define PCI_PRODUCT_BROADCOM_BCM5821 0x5821 /* BCM5821 Super-eCommerce Processor */
+#define PCI_PRODUCT_BROADCOM_BCM5850 0x5850 /* BCM5850 SSL/TLS Protocol Processor */
+
+/* Brooktree products */
+#define PCI_PRODUCT_BROOKTREE_BT848 0x0350 /* Bt848 Video Capture */
+#define PCI_PRODUCT_BROOKTREE_BT849 0x0351 /* Bt849 Video Capture */
+#define PCI_PRODUCT_BROOKTREE_BT878 0x036e /* Bt878 Video Capture */
+#define PCI_PRODUCT_BROOKTREE_BT879 0x036f /* Bt879 Video Capture */
+
+/* BusLogic products */
+#define PCI_PRODUCT_BUSLOGIC_MULTIMASTER_NC 0x0140 /* MultiMaster NC */
+#define PCI_PRODUCT_BUSLOGIC_MULTIMASTER 0x1040 /* MultiMaster */
+#define PCI_PRODUCT_BUSLOGIC_FLASHPOINT 0x8130 /* FlashPoint */
+
+/* c't Magazin products */
+#define PCI_PRODUCT_C4T_GPPCI 0x6773 /* GPPCI */
+
+/* Chips and Technologies products */
+#define PCI_PRODUCT_CHIPS_64310 0x00b8 /* 64310 */
+#define PCI_PRODUCT_CHIPS_65545 0x00d8 /* 65545 */
+#define PCI_PRODUCT_CHIPS_65548 0x00dc /* 65548 */
+#define PCI_PRODUCT_CHIPS_65550 0x00e0 /* 65550 */
+#define PCI_PRODUCT_CHIPS_65554 0x00e4 /* 65554 */
+
+/* Cirrus Logic products */
+#define PCI_PRODUCT_CIRRUS_CL_GD7548 0x0038 /* CL-GD7548 */
+#define PCI_PRODUCT_CIRRUS_CL_GD5430 0x00a0 /* CL-GD5430 */
+#define PCI_PRODUCT_CIRRUS_CL_GD5434_4 0x00a4 /* CL-GD5434-4 */
+#define PCI_PRODUCT_CIRRUS_CL_GD5434_8 0x00a8 /* CL-GD5434-8 */
+#define PCI_PRODUCT_CIRRUS_CL_GD5436 0x00ac /* CL-GD5436 */
+#define PCI_PRODUCT_CIRRUS_CL_GD5446 0x00b8 /* CL-GD5446 */
+#define PCI_PRODUCT_CIRRUS_CL_GD5480 0x00bc /* CL-GD5480 */
+#define PCI_PRODUCT_CIRRUS_CL_PD6729 0x1100 /* CL-PD6729 */
+#define PCI_PRODUCT_CIRRUS_CL_PD6832 0x1110 /* CL-PD6832 PCI-CardBus Bridge */
+#define PCI_PRODUCT_CIRRUS_CL_PD6833 0x1113 /* CL-PD6833 PCI-CardBus Bridge */
+#define PCI_PRODUCT_CIRRUS_CL_GD7542 0x1200 /* CL-GD7542 */
+#define PCI_PRODUCT_CIRRUS_CL_GD7543 0x1202 /* CL-GD7543 */
+#define PCI_PRODUCT_CIRRUS_CL_GD7541 0x1204 /* CL-GD7541 */
+#define PCI_PRODUCT_CIRRUS_CL_CD4400 0x4400 /* CL-CD4400 Communications Controller */
+#define PCI_PRODUCT_CIRRUS_CS4610 0x6001 /* CS4610 SoundFusion Audio Accelerator */
+#define PCI_PRODUCT_CIRRUS_CS4280 0x6003 /* CS4280 CrystalClear Audio Interface */
+
+/* CMD Technology products -- info gleaned from their web site */
+#define PCI_PRODUCT_CMDTECH_640 0x0640 /* PCI0640 */
+/* No data on the CMD Tech. web site for the following as of Mar. 3 '98 */
+#define PCI_PRODUCT_CMDTECH_642 0x0642 /* PCI0642 */
+/* datasheets available from www.cmd.com for the followings */
+#define PCI_PRODUCT_CMDTECH_643 0x0643 /* PCI0643 */
+#define PCI_PRODUCT_CMDTECH_646 0x0646 /* PCI0646 */
+#define PCI_PRODUCT_CMDTECH_647 0x0647 /* PCI0647 */
+#define PCI_PRODUCT_CMDTECH_648 0x0648 /* PCI0648 */
+#define PCI_PRODUCT_CMDTECH_649 0x0649 /* PCI0649 */
+
+/* Inclusion of 'A' in the following entry is probably wrong. */
+/* No data on the CMD Tech. web site for the following as of Mar. 3 '98 */
+#define PCI_PRODUCT_CMDTECH_650A 0x0650 /* PCI0650A */
+#define PCI_PRODUCT_CMDTECH_670 0x0670 /* USB0670 */
+#define PCI_PRODUCT_CMDTECH_673 0x0673 /* USB0673 */
+
+/* C-Media products */
+#define PCI_PRODUCT_CMEDIA_CMI8338A 0x0100 /* CMI8338A PCI Audio Device */
+#define PCI_PRODUCT_CMEDIA_CMI8338B 0x0101 /* CMI8338B PCI Audio Device */
+#define PCI_PRODUCT_CMEDIA_CMI8738 0x0111 /* CMI8738/C3DX PCI Audio Device */
+#define PCI_PRODUCT_CMEDIA_HSP56 0x0211 /* HSP56 Audiomodem Riser */
+
+/* Cogent Data Technologies products */
+#define PCI_PRODUCT_COGENT_EM110TX 0x1400 /* EX110TX PCI Fast Ethernet Adapter */
+
+/* Compaq products */
+#define PCI_PRODUCT_COMPAQ_PCI_EISA_BRIDGE 0x0001 /* PCI-EISA Bridge */
+#define PCI_PRODUCT_COMPAQ_PCI_ISA_BRIDGE 0x0002 /* PCI-ISA Bridge */
+#define PCI_PRODUCT_COMPAQ_TRIFLEX1 0x1000 /* Triflex Host-PCI Bridge */
+#define PCI_PRODUCT_COMPAQ_TRIFLEX2 0x2000 /* Triflex Host-PCI Bridge */
+#define PCI_PRODUCT_COMPAQ_QVISION_V0 0x3032 /* QVision */
+#define PCI_PRODUCT_COMPAQ_QVISION_1280P 0x3033 /* QVision 1280/p */
+#define PCI_PRODUCT_COMPAQ_QVISION_V2 0x3034 /* QVision */
+#define PCI_PRODUCT_COMPAQ_TRIFLEX4 0x4000 /* Triflex Host-PCI Bridge */
+#define PCI_PRODUCT_COMPAQ_USB 0x7020 /* USB Controller */
+#define PCI_PRODUCT_COMPAQ_SMART2P 0xae10 /* SMART2P RAID */
+#define PCI_PRODUCT_COMPAQ_N100TX 0xae32 /* Netelligent 10/100 TX */
+#define PCI_PRODUCT_COMPAQ_N10T 0xae34 /* Netelligent 10 T */
+#define PCI_PRODUCT_COMPAQ_IntNF3P 0xae35 /* Integrated NetFlex 3/P */
+#define PCI_PRODUCT_COMPAQ_DPNet100TX 0xae40 /* Dual Port Netelligent 10/100 TX */
+#define PCI_PRODUCT_COMPAQ_IntPL100TX 0xae43 /* ProLiant Integrated Netelligent 10/100 TX */
+#define PCI_PRODUCT_COMPAQ_DP4000 0xb011 /* Deskpro 4000 5233MMX */
+#define PCI_PRODUCT_COMPAQ_NF3P_BNC 0xf150 /* NetFlex 3/P w/ BNC */
+#define PCI_PRODUCT_COMPAQ_NF3P 0xf130 /* NetFlex 3/P */
+
+/* Compex products - XXX better descriptions */
+#define PCI_PRODUCT_COMPEX_NE2KETHER 0x1401 /* Ethernet */
+#define PCI_PRODUCT_COMPEX_RL100ATX 0x2011 /* RL100-ATX 10/100 Ethernet */
+#define PCI_PRODUCT_COMPEX_RL100TX 0x9881 /* RL100-TX 10/100 Ethernet */
+
+/* Conexant Systems products */
+#define PCI_PRODUCT_CONEXANT_SOFTK56 0x2443 /* SoftK56 PCI Software Modem */
+
+/* Contaq Microsystems products */
+#define PCI_PRODUCT_CONTAQ_82C599 0x0600 /* 82C599 PCI-VLB Bridge */
+#define PCI_PRODUCT_CONTAQ_82C693 0xc693 /* 82C693 PCI-ISA Bridge */
+
+/* Corollary Products */
+#define PCI_PRODUCT_COROLLARY_CBUSII_PCIB 0x0014 /* \"C-Bus II\"-PCI Bridge */
+
+/* Creative Labs products */
+#define PCI_PRODUCT_CREATIVELABS_SBLIVE 0x0002 /* SBLive! EMU 10000 */
+#define PCI_PRODUCT_CREATIVELABS_SBJOY 0x7002 /* PCI Gameport Joystick */
+#define PCI_PRODUCT_CREATIVELABS_EV1938 0x8938 /* Ectiva 1938 */
+
+/* Cyclades products */
+#define PCI_PRODUCT_CYCLADES_CYCLOMY_1 0x0100 /* Cyclom-Y below 1M */
+#define PCI_PRODUCT_CYCLADES_CYCLOMY_2 0x0101 /* Cyclom-Y above 1M */
+#define PCI_PRODUCT_CYCLADES_CYCLOM4Y_1 0x0102 /* Cyclom-4Y below 1M */
+#define PCI_PRODUCT_CYCLADES_CYCLOM4Y_2 0x0103 /* Cyclom-4Y above 1M */
+#define PCI_PRODUCT_CYCLADES_CYCLOM8Y_1 0x0104 /* Cyclom-8Y below 1M */
+#define PCI_PRODUCT_CYCLADES_CYCLOM8Y_2 0x0105 /* Cyclom-8Y above 1M */
+#define PCI_PRODUCT_CYCLADES_CYCLOMZ_1 0x0200 /* Cyclom-Z below 1M */
+#define PCI_PRODUCT_CYCLADES_CYCLOMZ_2 0x0201 /* Cyclom-Z above 1M */
+
+/* Davicom Semiconductor products */
+#define PCI_PRODUCT_DAVICOM_DM9102 0x9102 /* Davicom DM9102 10/100 Ethernet */
+
+/* DEC products */
+#define PCI_PRODUCT_DEC_21050 0x0001 /* DECchip 21050 PCI-PCI Bridge */
+#define PCI_PRODUCT_DEC_21040 0x0002 /* DECchip 21040 Ethernet */
+#define PCI_PRODUCT_DEC_21030 0x0004 /* DECchip 21030 (\"TGA\") */
+#define PCI_PRODUCT_DEC_NVRAM 0x0007 /* Zephyr NV-RAM */
+#define PCI_PRODUCT_DEC_KZPSA 0x0008 /* KZPSA */
+#define PCI_PRODUCT_DEC_21140 0x0009 /* DECchip 21140 10/100 Ethernet */
+#define PCI_PRODUCT_DEC_PBXGB 0x000d /* TGA2 */
+#define PCI_PRODUCT_DEC_DEFPA 0x000f /* DEFPA */
+/* product DEC ??? 0x0010 ??? VME Interface */
+#define PCI_PRODUCT_DEC_21041 0x0014 /* DECchip 21041 Ethernet */
+#define PCI_PRODUCT_DEC_DGLPB 0x0016 /* DGLPB (\"OPPO\") */
+#define PCI_PRODUCT_DEC_21142 0x0019 /* DECchip 21142/21143 10/100 Ethernet */
+#define PCI_PRODUCT_DEC_21052 0x0021 /* DECchip 21052 PCI-PCI Bridge */
+#define PCI_PRODUCT_DEC_21150 0x0022 /* DECchip 21150 PCI-PCI Bridge */
+#define PCI_PRODUCT_DEC_21152 0x0024 /* DECchip 21152 PCI-PCI Bridge */
+#define PCI_PRODUCT_DEC_21153 0x0025 /* DECchip 21153 PCI-PCI Bridge */
+#define PCI_PRODUCT_DEC_21154 0x0026 /* DECchip 21154 PCI-PCI Bridge */
+#define PCI_PRODUCT_DEC_CPQ42XX 0x0046 /* Compaq SMART RAID 42xx */
+
+/* Delta products */
+#define PCI_PRODUCT_DELTA_8139 0x1360 /* 8139 Ethernet */
+
+/* Diamond products */
+#define PCI_PRODUCT_DIAMOND_VIPER 0x9001 /* Viper/PCI */
+
+/* D-Link Systems products */
+#define PCI_PRODUCT_DLINK_DFE550TX 0x1002 /* DFE-550TX 10/100 Ethernet */
+
+/* Distributed Processing Technology products */
+#define PCI_PRODUCT_DPT_SC_RAID 0xa400 /* SmartCache/SmartRAID */
+#define PCI_PRODUCT_DPT_RAID_I2O 0xa501 /* SmartRAID (I2O) */
+#define PCI_PRODUCT_DPT_MEMCTLR 0x1012 /* Memory Controller */
+
+/* Dolphin products */
+#define PCI_PRODUCT_DOLPHIN_PCISCI 0x0658 /* PCI-SCI Bridge */
+
+/* Domex products */
+#define PCI_PRODUCT_DOMEX_PCISCSI 0x0001 /* DMX-3191D */
+
+/* ELSA products */
+#define PCI_PRODUCT_ELSA_QS1PCI 0x1000 /* QuickStep 1000 ISDN card */
+
+/* Emulex products */
+#define PCI_PRODUCT_EMULEX_LPPFC 0x10df /* \"Light Pulse\" FibreChannel adapter */
+
+/* Ensoniq products */
+#define PCI_PRODUCT_ENSONIQ_AUDIOPCI 0x5000 /* AudioPCI */
+#define PCI_PRODUCT_ENSONIQ_AUDIOPCI97 0x1371 /* AudioPCI 97 */
+#define PCI_PRODUCT_ENSONIQ_CT5880 0x5880 /* CT5880 */
+
+/* Epigram (now Broadcom) products */
+#define PCI_PRODUCT_EPIGRAM_BCM4210 0xa0fa /* BCM4210 iLine10 Controller */
+
+/* Essential Communications products */
+#define PCI_PRODUCT_ESSENTIAL_RR_HIPPI 0x0001 /* RoadRunner HIPPI Interface */
+#define PCI_PRODUCT_ESSENTIAL_RR_GIGE 0x0005 /* RoadRunner Gig-E Interface */
+
+/* ESS Technology Inc products */
+#define PCI_PRODUCT_ESSTECH_MAESTRO1 0x0100 /* Maestro 1 PCI Audio Accelerator */
+#define PCI_PRODUCT_ESSTECH_MAESTRO2 0x1968 /* Maestro 2 PCI Audio Accelerator */
+#define PCI_PRODUCT_ESSTECH_SOLO1 0x1969 /* Solo-1 PCI AudioDrive */
+#define PCI_PRODUCT_ESSTECH_MAESTRO2E 0x1978 /* Maestro 2E PCI Audio Accelerator */
+#define PCI_PRODUCT_ESSTECH_MAESTRO3 0x1998 /* Maestro 3 PCI Audio Accelerator */
+#define PCI_PRODUCT_ESSTECH_MAESTRO3MODEM 0x1999 /* Maestro 3 Modem */
+
+/* ESS Technology Inc products */
+#define PCI_PRODUCT_ESSTECH2_MAESTRO1 0x0100 /* Maestro 1 PCI Audio Accelerator */
+
+/* O2 Micro Inc */
+#define PCI_PRODUCT_O2MICRO_OZ6832 0x6832 /* OZ6832 CardBus Controller */
+
+/* Evans & Sutherland products */
+#define PCI_PRODUCT_ES_FREEDOM 0x0001 /* Freedom PCI-GBus Interface */
+
+/* FORE products */
+#define PCI_PRODUCT_FORE_PCA200 0x0210 /* ATM PCA-200 */
+#define PCI_PRODUCT_FORE_PCA200E 0x0300 /* ATM PCA-200e */
+
+/* Forte Media products */
+#define PCI_PRODUCT_FORTEMEDIA_FM801 0x0801 /* Forte Media 801 Sound */
+
+/* Future Domain products */
+#define PCI_PRODUCT_FUTUREDOMAIN_TMC_18C30 0x0000 /* TMC-18C30 (36C70) */
+
+/* Efficient Networks products */
+#define PCI_PRODUCT_EFFICIENTNETS_ENI155PF 0x0000 /* 155P-MF1 ATM (FPGA) */
+#define PCI_PRODUCT_EFFICIENTNETS_ENI155PA 0x0002 /* 155P-MF1 ATM (ASIC) */
+#define PCI_PRODUCT_EFFICIENTNETS_ENI25P 0x0003 /* SpeedStream ENI-25p */
+#define PCI_PRODUCT_EFFICIENTNETS_SS3000 0x0005 /* SpeedStream 3000 */
+
+/* Galileo Technology products */
+#define PCI_PRODUCT_GALILEO_GT64010A 0x0146 /* GT-64010A System Controller */
+#define PCI_PRODUCT_GALILEO_GT64115 0x4111 /* GT-64115 System Controller */
+#define PCI_PRODUCT_GALILEO_GT64011 0x4146 /* GT-64011 System Controller */
+#define PCI_PRODUCT_GALILEO_GT64120 0x4620 /* GT-64120 System Controller */
+#define PCI_PRODUCT_GALILEO_GT64130 0x6320 /* GT-64130 System Controller */
+
+/* Hewlett-Packard products */
+#define PCI_PRODUCT_HP_J2585A 0x1030 /* J2585A */
+
+/* IBM products */
+#define PCI_PRODUCT_IBM_MCABRIDGE 0x0002 /* MCA Bridge */
+#define PCI_PRODUCT_IBM_ALTALITE 0x0005 /* CPU Bridge - Alta Lite */
+#define PCI_PRODUCT_IBM_ALTAMP 0x0007 /* CPU Bridge - Alta MP */
+#define PCI_PRODUCT_IBM_ISABRIDGE 0x000a /* ISA Bridge w/PnP */
+#define PCI_PRODUCT_IBM_CPUBRIDGE 0x0017 /* CPU Bridge */
+#define PCI_PRODUCT_IBM_LANSTREAMER 0x0018 /* Auto LANStreamer */
+#define PCI_PRODUCT_IBM_GXT150P 0x001b /* GXT-150P 2D Accelerator */
+#define PCI_PRODUCT_IBM_MCABRIDGE2 0x0020 /* MCA Bridge */
+#define PCI_PRODUCT_IBM_82351 0x0022 /* 82351 PCI-PCI Bridge */
+#define PCI_PRODUCT_IBM_SERVERAID 0x002e /* ServeRAID */
+#define PCI_PRODUCT_IBM_OLYMPIC 0x003e /* Token Ring */
+#define PCI_PRODUCT_IBM_MIAMI 0x0036 /* Miami/PCI */
+#define PCI_PRODUCT_IBM_TURBOWAYS25 0x0053 /* Turboways 25 ATM */
+#define PCI_PRODUCT_IBM_MPIC2 0xffff /* MPIC-II */
+
+/* IDT products */
+#define PCI_PRODUCT_IDT_77201 0x0001 /* 77201/77211 ATM (\"NICStAR\") */
+
+/* Initio products */
+#define PCI_PRODUCT_INITIO_I920 0x0002 /* INIC-920 SCSI */
+#define PCI_PRODUCT_INITIO_I940 0x9400 /* INIC-940 SCSI */
+#define PCI_PRODUCT_INITIO_I935 0x9401 /* INIC-935 SCSI */
+#define PCI_PRODUCT_INITIO_I950 0x9500 /* INIC-950 SCSI */
+
+/* Integrated Micro Solutions products */
+#define PCI_PRODUCT_IMS_8849 0x8849 /* 8849 */
+#define PCI_PRODUCT_IMS_TT128M 0x9128 /* TwinTurbo 128M */
+
+/* Intel products */
+#define PCI_PRODUCT_INTEL_PCEB 0x0482 /* 82375EB/SB PCI-EISA Bridge (PCEB) */
+#define PCI_PRODUCT_INTEL_CDC 0x0483 /* 82424ZX Cache and DRAM controller (CDC) */
+#define PCI_PRODUCT_INTEL_SIO 0x0484 /* 82378ZB System I/O (SIO) */
+#define PCI_PRODUCT_INTEL_82426EX 0x0486 /* 82426EX PCI-to-ISA Bridge (PCIB) */
+#define PCI_PRODUCT_INTEL_PCMC 0x04a3 /* 82434LX/NX PCI, Cache and Memory Controller (PCMC) */
+#define PCI_PRODUCT_INTEL_IN_BUSINESS 0x1030 /* InBusiness Fast Ethernet LAN Controller */
+#define PCI_PRODUCT_INTEL_82559ER 0x1209 /* 82559ER Fast Ethernet LAN Controller */
+#define PCI_PRODUCT_INTEL_82092AA 0x1222 /* 82092AA IDE controller */
+#define PCI_PRODUCT_INTEL_SAA7116 0x1223 /* SAA7116 */
+#define PCI_PRODUCT_INTEL_82596 0x1226 /* 82596 LAN Controller */
+#define PCI_PRODUCT_INTEL_EEPRO100 0x1227 /* EE Pro 100 10/100 Fast Ethernet */
+#define PCI_PRODUCT_INTEL_EEPRO100S 0x1228 /* EE Pro 100 Smart 10/100 Fast Ethernet */
+#define PCI_PRODUCT_INTEL_82557 0x1229 /* 82557 Fast Ethernet LAN Controller */
+#define PCI_PRODUCT_INTEL_82437FX 0x122d /* 82437FX System Controller (TSC) */
+#define PCI_PRODUCT_INTEL_82371FB_ISA 0x122e /* 82371FB PCI-to-ISA Bridge (PIIX) */
+#define PCI_PRODUCT_INTEL_82371FB_IDE 0x1230 /* 82371FB IDE controller (PIIX) */
+#define PCI_PRODUCT_INTEL_82371MX 0x1234 /* 82371MX Mobile PCI I/O IDE Xcelerator (MPIIX) */
+#define PCI_PRODUCT_INTEL_82437MX 0x1235 /* 82437MX Mobile System Controller (MTSC) */
+#define PCI_PRODUCT_INTEL_82441FX 0x1237 /* 82441FX PCI and Memory Controller (PMC) */
+#define PCI_PRODUCT_INTEL_82380AB 0x123c /* 82380AB Mobile PCI-to-ISA Bridge (MISA) */
+#define PCI_PRODUCT_INTEL_82380FB 0x124b /* 82380FB Mobile PCI-to-PCI Bridge (MPCI2) */
+#define PCI_PRODUCT_INTEL_82439HX 0x1250 /* 82439HX System Controller (TXC) */
+#define PCI_PRODUCT_INTEL_82801AA_LPC 0x2410 /* 82801AA LPC Interface Bridge */
+#define PCI_PRODUCT_INTEL_82801AA_IDE 0x2411 /* 82801AA IDE Controller */
+#define PCI_PRODUCT_INTEL_82801AA_USB 0x2412 /* 82801AA USB Controller */
+#define PCI_PRODUCT_INTEL_82801AA_SMB 0x2413 /* 82801AA SMBus Controller */
+#define PCI_PRODUCT_INTEL_82801AA_ACA 0x2415 /* 82801AA AC-97 Audio Controller */
+#define PCI_PRODUCT_INTEL_82801AA_ACM 0x2416 /* 82801AA AC-97 PCI Modem */
+#define PCI_PRODUCT_INTEL_82801AA_HPB 0x2418 /* 82801AA Hub-to-PCI Bridge */
+#define PCI_PRODUCT_INTEL_82801AB_LPC 0x2420 /* 82801AB LPC Interface Bridge */
+#define PCI_PRODUCT_INTEL_82801AB_IDE 0x2421 /* 82801AB IDE Controller */
+#define PCI_PRODUCT_INTEL_82801AB_USB 0x2422 /* 82801AB USB Controller */
+#define PCI_PRODUCT_INTEL_82801AB_SMB 0x2423 /* 82801AB SMBus Controller */
+#define PCI_PRODUCT_INTEL_82801AB_ACA 0x2425 /* 82801AB AC-97 Audio Controller */
+#define PCI_PRODUCT_INTEL_82801AB_ACM 0x2426 /* 82801AB AC-97 PCI Modem */
+#define PCI_PRODUCT_INTEL_82801AB_HPB 0x2428 /* 82801AB Hub-to-PCI Bridge */
+#define PCI_PRODUCT_INTEL_82801BA_LPC 0x2440 /* 82801BA LPC Interface Bridge */
+#define PCI_PRODUCT_INTEL_82801BA_USB1 0x2442 /* 82801BA USB Controller */
+#define PCI_PRODUCT_INTEL_82801BA_SMB 0x2443 /* 82801BA SMBus Controller */
+#define PCI_PRODUCT_INTEL_82801BA_USB2 0x2444 /* 82801BA USB Controller */
+#define PCI_PRODUCT_INTEL_82801BA_ACA 0x2445 /* 82801BA AC-97 Audio Controller */
+#define PCI_PRODUCT_INTEL_82801BA_ACM 0x2446 /* 82801BA AC-97 PCI Modem */
+#define PCI_PRODUCT_INTEL_82801BA_LAN 0x2449 /* 82801BA LAN Controller */
+#define PCI_PRODUCT_INTEL_82801BA_IDE 0x244B /* 82801BA IDE Controller */
+#define PCI_PRODUCT_INTEL_82801BA_HPB 0x244E /* 82801BA Hub-to-PCI Bridge */
+#define PCI_PRODUCT_INTEL_82371SB_ISA 0x7000 /* 82371SB PCI-to-ISA Bridge (PIIX3) */
+#define PCI_PRODUCT_INTEL_82371SB_IDE 0x7010 /* 82371SB IDE Interface (PIIX3) */
+#define PCI_PRODUCT_INTEL_82371SB_USB 0x7020 /* 82371SB USB Host Controller (PIIX3) */
+#define PCI_PRODUCT_INTEL_82437VX 0x7030 /* 82437VX System Controller (TVX) */
+#define PCI_PRODUCT_INTEL_82439TX 0x7100 /* 82439TX System Controller (MTXC) */
+#define PCI_PRODUCT_INTEL_82371AB_ISA 0x7110 /* 82371AB PCI-to-ISA Bridge (PIIX4) */
+#define PCI_PRODUCT_INTEL_82371AB_IDE 0x7111 /* 82371AB IDE controller (PIIX4) */
+#define PCI_PRODUCT_INTEL_82371AB_USB 0x7112 /* 82371AB USB Host Controller (PIIX4) */
+#define PCI_PRODUCT_INTEL_82371AB_PMC 0x7113 /* 82371AB Power Management Controller (PIIX4) */
+#define PCI_PRODUCT_INTEL_82810_MCH 0x7120 /* 82810 Memory Controller Hub */
+#define PCI_PRODUCT_INTEL_82810_GC 0x7121 /* 82810 Graphics Controller */
+#define PCI_PRODUCT_INTEL_82810_DC100_MCH 0x7122 /* 82810-DC100 Memory Controller Hub */
+#define PCI_PRODUCT_INTEL_82810_DC100_GC 0x7123 /* 82810-DC100 Graphics Controller */
+#define PCI_PRODUCT_INTEL_82810E_MCH 0x7124 /* 82810E Memory Controller Hub */
+#define PCI_PRODUCT_INTEL_82810E_GC 0x7125 /* 82810E Graphics Controller */
+#define PCI_PRODUCT_INTEL_82443LX 0x7180 /* 82443LX PCI AGP Controller (PAC) */
+#define PCI_PRODUCT_INTEL_82443LX_AGP 0x7181 /* 82443LX AGP Interface (PAC) */
+#define PCI_PRODUCT_INTEL_82443BX 0x7190 /* 82443BX Host Bridge/Controller */
+#define PCI_PRODUCT_INTEL_82443BX_AGP 0x7191 /* 82443BX AGP Interface */
+#define PCI_PRODUCT_INTEL_82443BX_NOAGP 0x7192 /* 82443BX Host Bridge/Controller (AGP disabled) */
+#define PCI_PRODUCT_INTEL_82440MX 0x7194 /* 82440MX Host Bridge/Controller */
+#define PCI_PRODUCT_INTEL_82440MX_ACA 0x7195 /* 82440MX AC-97 Audio Controller */
+#define PCI_PRODUCT_INTEL_82440MX_ISA 0x7198 /* 82440MX PCI-to-ISA Bridge */
+#define PCI_PRODUCT_INTEL_82440MX_IDE 0x7199 /* 82440MX IDE Controller */
+#define PCI_PRODUCT_INTEL_82440MX_USB 0x719a /* 82440MX USB Host Controller */
+#define PCI_PRODUCT_INTEL_82440MX_PMC 0x719b /* 82440MX Power Management Controller */
+#define PCI_PRODUCT_INTEL_I740 0x7800 /* i740 Graphics Accelerator */
+#define PCI_PRODUCT_INTEL_PCI450_PB 0x84c4 /* 82454KX/GX PCI Bridge (PB) */
+#define PCI_PRODUCT_INTEL_PCI450_MC 0x84c5 /* 82451KX/GX Memory Controller (MC) */
+#define PCI_PRODUCT_INTEL_82451NX_MIOC 0x84ca /* 82451NX Memory & I/O Controller (MIOC) */
+#define PCI_PRODUCT_INTEL_82451NX_PXB 0x84cb /* 82451NX PCI Expander Bridge (PXB) */
+
+/* Intergraph products */
+#define PCI_PRODUCT_INTERGRAPH_4D50T 0x00e4 /* Powerstorm 4D50T */
+
+/* I. T. T. products */
+#define PCI_PRODUCT_ITT_AGX016 0x0001 /* AGX016 */
+#define PCI_PRODUCT_ITT_ITT3204 0x0002 /* ITT3204 MPEG Decoder */
+
+/* KTI products - XXX better descriptions */
+#define PCI_PRODUCT_KTI_NE2KETHER 0x3000 /* Ethernet */
+
+/* LAN Media Corporation */
+#define PCI_PRODUCT_LMC_HSSI 0x0003 /* HSSI Interface */
+#define PCI_PRODUCT_LMC_DS3 0x0004 /* DS3 Interface */
+#define PCI_PRODUCT_LMC_SSI 0x0005 /* SSI */
+
+/* LeadTek Research */
+#define PCI_PRODUCT_LEADTEK_S3_805 0x0000 /* S3 805 */
+
+/* Linear Systems / CompuModules */
+#define PCI_PRODUCT_LINEARSYS_DVB_TX 0x7629 /* DVB Transmitter */
+#define PCI_PRODUCT_LINEARSYS_DVB_RX 0x7630 /* DVB Receiver */
+
+/* Lite-On products */
+#define PCI_PRODUCT_LITEON_82C168 0x0002 /* 82C168/82C169 (PNIC) 10/100 Ethernet */
+#define PCI_PRODUCT_LITEON_82C115 0xc115 /* 82C115 (PNIC II) 10/100 Ethernet */
+
+/* Lucent products */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0440 0x0440 /* K56flex DSVD LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0441 0x0441 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0442 0x0442 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0443 0x0443 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0444 0x0444 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0445 0x0445 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0446 0x0446 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0447 0x0447 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0448 0x0448 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0449 0x0449 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_044A 0x044A /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_044B 0x044B /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_044C 0x044C /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_044D 0x044D /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_044E 0x044E /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0450 0x0450 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0451 0x0451 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0452 0x0452 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0453 0x0453 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0454 0x0454 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0455 0x0455 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0456 0x0456 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0457 0x0457 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0458 0x0458 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_0459 0x0459 /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_LTMODEM_045A 0x045A /* LTMODEM */
+#define PCI_PRODUCT_LUCENT_USBHC 0x5801 /* USB Host Controller */
+
+/* Macronix */
+#define PCI_PRODUCT_MACRONIX_MX98713 0x0512 /* MX98713 (PMAC) 10/100 Ethernet */
+#define PCI_PRODUCT_MACRONIX_MX987x5 0x0531 /* MX987x5 (PMAC) 10/100 Ethernet */
+
+/* Madge Networks products */
+#define PCI_PRODUCT_MADGE_COLLAGE25 0x1000 /* Collage 25 ATM adapter */
+#define PCI_PRODUCT_MADGE_COLLAGE155 0x1001 /* Collage 155 ATM adapter */
+
+/* Matrox products */
+#define PCI_PRODUCT_MATROX_ATLAS 0x0518 /* MGA PX2085 (\"Atlas\") */
+#define PCI_PRODUCT_MATROX_MILLENNIUM 0x0519 /* MGA Millennium 2064W */
+#define PCI_PRODUCT_MATROX_MYSTIQUE 0x051a /* MGA Mystique 1064SG */
+#define PCI_PRODUCT_MATROX_MILLENNIUM2 0x051b /* MGA Millennium II 2164W */
+#define PCI_PRODUCT_MATROX_MILLENNIUM2_AGP 0x051f /* MGA Millennium II 2164WA-B AG */
+#define PCI_PRODUCT_MATROX_G200_PCI 0x0520 /* MGA G200 PCI */
+#define PCI_PRODUCT_MATROX_G200_AGP 0x0521 /* MGA G200 AGP */
+#define PCI_PRODUCT_MATROX_G400_AGP 0x0525 /* MGA G400 AGP */
+#define PCI_PRODUCT_MATROX_IMPRESSION 0x0d10 /* MGA Impression */
+#define PCI_PRODUCT_MATROX_G100_PCI 0x1000 /* MGA G100 PCI */
+#define PCI_PRODUCT_MATROX_G100_AGP 0x1001 /* MGA G100 AGP */
+
+/* Motorola products */
+#define PCI_PRODUCT_MOT_MPC105 0x0001 /* MPC105 \"Eagle\" Host Bridge */
+#define PCI_PRODUCT_MOT_MPC106 0x0002 /* MPC106 \"Grackle\" Host Bridge */
+
+/* Mylex products */
+#define PCI_PRODUCT_MYLEX_960P 0x0001 /* DAC960P RAID controller */
+
+/* Mutech products */
+#define PCI_PRODUCT_MUTECH_MV1000 0x0001 /* MV1000 */
+
+/* NetVin products - XXX better descriptions */
+#define PCI_PRODUCT_NETVIN_5000 0x5000 /* 5000 Ethernet */
+
+/* Newbridge / Tundra products */
+#define PCI_PRODUCT_NEWBRIDGE_CA91CX42 0x0000 /* Universe VME bridge */
+
+/* National Semiconductor products */
+#define PCI_PRODUCT_NS_DP83810 0x0001 /* DP83810 10/100 Ethernet */
+#define PCI_PRODUCT_NS_DP83815 0x0020 /* DP83815 10/100 Ethernet */
+#define PCI_PRODUCT_NS_NS87410 0xd001 /* NS87410 */
+
+/* NCR/Symbios Logic products */
+#define PCI_PRODUCT_SYMBIOS_810 0x0001 /* 53c810 */
+#define PCI_PRODUCT_SYMBIOS_820 0x0002 /* 53c820 */
+#define PCI_PRODUCT_SYMBIOS_825 0x0003 /* 53c825 */
+#define PCI_PRODUCT_SYMBIOS_815 0x0004 /* 53c815 */
+#define PCI_PRODUCT_SYMBIOS_810AP 0x0005 /* 53c810AP */
+#define PCI_PRODUCT_SYMBIOS_860 0x0006 /* 53c860 */
+#define PCI_PRODUCT_SYMBIOS_896 0x000b /* 53c896 */
+#define PCI_PRODUCT_SYMBIOS_895 0x000c /* 53c895 */
+#define PCI_PRODUCT_SYMBIOS_885 0x000d /* 53c885 */
+#define PCI_PRODUCT_SYMBIOS_875 0x000f /* 53c875 */
+#define PCI_PRODUCT_SYMBIOS_1510 0x0010 /* 53c1510 */
+#define PCI_PRODUCT_SYMBIOS_875J 0x008f /* 53c875J */
+
+/* Packet Engines products */
+#define PCI_PRODUCT_SYMBIOS_PE_GNIC 0x0702 /* Packet Engines G-NIC Ethernet */
+
+/* NEC products */
+#define PCI_PRODUCT_NEC_USB 0x0035 /* USB Host Controller */
+#define PCI_PRODUCT_NEC_POWERVR2 0x0046 /* PowerVR PCX2 */
+#define PCI_PRODUCT_NEC_PD72872 0x0063 /* uPD72872 IEEE 1394 OHCI Host Controller */
+#define PCI_PRODUCT_NEC_PD72870 0x00cd /* uPD72870 IEEE 1394 OHCI Host Controller */
+#define PCI_PRODUCT_NEC_PD72871 0x00ce /* uPD72871 IEEE 1394 OHCI Host Controller */
+
+/* Neomagic products */
+#define PCI_PRODUCT_NEOMAGIC_NMMG128ZV 0x0003 /* MagicGraph 128ZV */
+#define PCI_PRODUCT_NEOMAGIC_NMMG2160 0x0004 /* MagicGraph 128XD */
+#define PCI_PRODUCT_NEOMAGIC_NMMM256AV_VGA 0x0005 /* MagicMedia 256AV VGA */
+#define PCI_PRODUCT_NEOMAGIC_NMMM256ZX_VGA 0x0006 /* MagicMedia 256ZX VGA */
+#define PCI_PRODUCT_NEOMAGIC_NMMM256AV_AU 0x8005 /* MagicMedia 256AV Audio */
+#define PCI_PRODUCT_NEOMAGIC_NMMM256ZX_AU 0x8006 /* MagicMedia 256ZX Audio */
+
+/* Netgear products */
+#define PCI_PRODUCT_NETGEAR_GA620 0x620a /* GA620 Gigabit Ethernet */
+
+/* NexGen products */
+#define PCI_PRODUCT_NEXGEN_NX82C501 0x4e78 /* NX82C501 Host-PCI Bridge */
+
+/* NKK products */
+#define PCI_PRODUCT_NKK_NDR4600 0xA001 /* NDR4600 Host-PCI Bridge */
+
+/* Number Nine products */
+#define PCI_PRODUCT_NUMBER9_I128 0x2309 /* Imagine-128 */
+#define PCI_PRODUCT_NUMBER9_I128_2 0x2339 /* Imagine-128 II */
+
+/* Nvidia Corporationn products */
+#define PCI_PRODUCT_NVIDIA_RIVATNT 0x0020 /* RIVA TNT */
+#define PCI_PRODUCT_NVIDIA_RIVATNT2 0x0028 /* RIVA TNT2 */
+#define PCI_PRODUCT_NVIDIA_RIVATNT2U 0x0029 /* RIVA TNT2 Ultra */
+#define PCI_PRODUCT_NVIDIA_VANTA 0x002C /* Vanta */
+#define PCI_PRODUCT_NVIDIA_RIVATNT2M64 0x002D /* RIVA TNT2 Model 64 */
+#define PCI_PRODUCT_NVIDIA_ALADDINTNT2 0x00A0 /* Aladdin TNT2 */
+#define PCI_PRODUCT_NVIDIA_GEFORCE256 0x0100 /* GeForce 256 */
+#define PCI_PRODUCT_NVIDIA_GEFORCEDDR 0x0101 /* GeForce DDR */
+#define PCI_PRODUCT_NVIDIA_QUADRO 0x0103 /* Quadro */
+#define PCI_PRODUCT_NVIDIA_GEFORCE2 0x0150 /* GeForce2 GTS */
+#define PCI_PRODUCT_NVIDIA_GEFORCE2DDR 0x0151 /* GeForce2 GTS (DDR) */
+#define PCI_PRODUCT_NVIDIA_GEFORCE2BR 0x0152 /* GeForce2 GTS */
+#define PCI_PRODUCT_NVIDIA_QUADRO2 0x0153 /* Quadro2 */
+
+/* Nvidia Corporation & SGS Thomson Microelectric */
+#define PCI_PRODUCT_NVIDIA_SGS_RIVA128 0x0018 /* Riva 128 */
+
+/* Oak Technologies products */
+#define PCI_PRODUCT_OAKTECH_OTI1007 0x0107 /* OTI107 */
+
+/* Olicom products */
+#define PCI_PRODUCT_OLICOM_OC2183 0x0013 /* Olicom OC-2183/2185 Ethernet */
+#define PCI_PRODUCT_OLICOM_OC2325 0x0012 /* Olicom OC-2325 Ethernet */
+#define PCI_PRODUCT_OLICOM_OC2326 0x0014 /* Olicom OC-2326 10/100-TX Ethernet */
+
+/* Opti products */
+#define PCI_PRODUCT_OPTI_82C557 0xc557 /* 82C557 */
+#define PCI_PRODUCT_OPTI_82C558 0xc558 /* 82C558 */
+#define PCI_PRODUCT_OPTI_82C568 0xc568 /* 82C568 */
+#define PCI_PRODUCT_OPTI_82D568 0xd568 /* 82D568 */
+#define PCI_PRODUCT_OPTI_82C621 0xc621 /* 82C621 */
+#define PCI_PRODUCT_OPTI_82C822 0xc822 /* 82C822 */
+#define PCI_PRODUCT_OPTI_RM861HA 0xc861 /* RM861HA */
+#define PCI_PRODUCT_OPTI_82C700 0xc700 /* 82C700 */
+#define PCI_PRODUCT_OPTI_82C701 0xc701 /* 82C701 */
+
+/* PC Tech products */
+#define PCI_PRODUCT_PCTECH_RZ1000 0x1000 /* RZ1000 */
+
+/* PLX Technology products */
+#define PCI_PRODUCT_PLX_9060ES 0x906e /* 9060ES PCI bus controller */
+
+/* ProLAN products - XXX better descriptions */
+#define PCI_PRODUCT_PROLAN_NE2KETHER 0x1980 /* Ethernet */
+
+/* Promise products */
+#define PCI_PRODUCT_PROMISE_DC5030 0x5300 /* DC5030 */
+#define PCI_PRODUCT_PROMISE_ULTRA33 0x4d33 /* Ultra33/ATA Bus Master IDE Accelerator */
+#define PCI_PRODUCT_PROMISE_ULTRA66 0x4d38 /* Ultra66/ATA Bus Master IDE Accelerator */
+#define PCI_PRODUCT_PROMISE_ULTRA100 0x4d30 /* Ultra100/ATA Bus Master IDE Accelerator */
+
+/* QLogic products */
+#define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 /* ISP1020 */
+#define PCI_PRODUCT_QLOGIC_ISP1022 0x1022 /* ISP1022 */
+#define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 /* ISP1080 */
+#define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 /* ISP1240 */
+#define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 /* ISP2100 */
+
+/* Quantum Designs products */
+#define PCI_PRODUCT_QUANTUMDESIGNS_8500 0x0001 /* 8500 */
+#define PCI_PRODUCT_QUANTUMDESIGNS_8580 0x0002 /* 8580 */
+
+/* Realtek (Creative Labs?) products */
+#define PCI_PRODUCT_REALTEK_RT8029 0x8029 /* 8029 Ethernet */
+#define PCI_PRODUCT_REALTEK_RT8129 0x8129 /* 8129 10/100 Ethernet */
+#define PCI_PRODUCT_REALTEK_RT8139 0x8139 /* 8139 10/100 Ethernet */
+
+/* RICOH products */
+#define PCI_PRODUCT_RICOH_Rx5C465 0x0465 /* 5C465 PCI-CardBus bridge */
+#define PCI_PRODUCT_RICOH_Rx5C466 0x0466 /* 5C466 PCI-CardBus bridge */
+#define PCI_PRODUCT_RICOH_Rx5C475 0x0475 /* 5C475 PCI-CardBus bridge */
+#define PCI_PRODUCT_RICOH_RL5C476 0x0476 /* 5C476 PCI-CardBus bridge */
+#define PCI_PRODUCT_RICOH_Rx5C477 0x0477 /* 5C477 PCI-CardBus bridge */
+#define PCI_PRODUCT_RICOH_Rx5C478 0x0478 /* 5C478 PCI-CardBus bridge */
+
+/* RISCom (SDL Communications, Inc?) products */
+#define PCI_PRODUCT_RISCOM_N2 0x5568 /* N2 */
+
+/* RNS products */
+#define PCI_PRODUCT_RNS_FDDI 0x2200 /* 2200 FDDI */
+
+/* S3 products */
+#define PCI_PRODUCT_S3_VIRGE 0x5631 /* ViRGE */
+#define PCI_PRODUCT_S3_TRIO32 0x8810 /* Trio32 */
+#define PCI_PRODUCT_S3_TRIO64 0x8811 /* Trio32/64 */
+#define PCI_PRODUCT_S3_AURORA64P 0x8812 /* Aurora64V+ */
+#define PCI_PRODUCT_S3_TRIO64UVP 0x8814 /* Trio64UV+ */
+#define PCI_PRODUCT_S3_VIRGE_VX 0x883d /* ViRGE/VX */
+#define PCI_PRODUCT_S3_868 0x8880 /* 868 */
+#define PCI_PRODUCT_S3_928 0x88b0 /* 86C928 */
+#define PCI_PRODUCT_S3_864_0 0x88c0 /* 86C864-0 */
+#define PCI_PRODUCT_S3_864_1 0x88c1 /* 86C864-1 */
+#define PCI_PRODUCT_S3_864_2 0x88c2 /* 86C864-2 */
+#define PCI_PRODUCT_S3_864_3 0x88c3 /* 86C864-3 */
+#define PCI_PRODUCT_S3_964_0 0x88d0 /* 86C964-0 */
+#define PCI_PRODUCT_S3_964_1 0x88d1 /* 86C964-1 */
+#define PCI_PRODUCT_S3_964_2 0x88d2 /* 86C964-2 */
+#define PCI_PRODUCT_S3_964_3 0x88d3 /* 86C964-3 */
+#define PCI_PRODUCT_S3_968_0 0x88f0 /* 86C968-0 */
+#define PCI_PRODUCT_S3_968_1 0x88f1 /* 86C968-1 */
+#define PCI_PRODUCT_S3_968_2 0x88f2 /* 86C968-2 */
+#define PCI_PRODUCT_S3_968_3 0x88f3 /* 86C968-3 */
+#define PCI_PRODUCT_S3_TRIO64V2_DX 0x8901 /* Trio64V2/DX */
+#define PCI_PRODUCT_S3_PLATO_PX 0x8901 /* Plato/PX */
+#define PCI_PRODUCT_S3_TRIO3D 0x8904 /* 86C365 Trio3D */
+#define PCI_PRODUCT_S3_VIRGE_DX 0x8a01 /* ViRGE/DX */
+#define PCI_PRODUCT_S3_VIRGE_GX2 0x8a10 /* ViRGE/GX2 */
+#define PCI_PRODUCT_S3_TRIO3D2X 0x8a13 /* Trio3D/2X */
+#define PCI_PRODUCT_S3_SAVAGE3D 0x8a20 /* Savage3D */
+#define PCI_PRODUCT_S3_SAVAGE3D_MV 0x8a21 /* Savage3D+MV */
+#define PCI_PRODUCT_S3_SAVAGE4 0x8a22 /* Savage4 */
+#define PCI_PRODUCT_S3_VIRGE_MX 0x8c01 /* ViRGE/MX */
+#define PCI_PRODUCT_S3_VIRGE_MXP 0x8c03 /* ViRGE/MXP */
+#define PCI_PRODUCT_S3_SAVAGE_MX_MV 0x8c10 /* Savage/MX+MV */
+#define PCI_PRODUCT_S3_SAVAGE_MX 0x8c11 /* Savage/MX */
+#define PCI_PRODUCT_S3_SAVAGE_IX_MV 0x8c12 /* Savage/IX+MV */
+#define PCI_PRODUCT_S3_SAVAGE_IX 0x8c13 /* Savage/IX */
+#define PCI_PRODUCT_S3_SAVAGE2000 0x9102 /* Savage2000 */
+#define PCI_PRODUCT_S3_SONICVIBES 0xca00 /* SonicVibes */
+
+/* Samsung Semiconductor products */
+#define PCI_PRODUCT_SAMSUNGSEMI_KS8920 0x8920 /* KS8920 10/100 Ethernet */
+
+/* SGI products */
+#define PCI_PRODUCT_SGI_IOC3 0x0003 /* IOC3 */
+#define PCI_PRODUCT_SGI_RAD1 0x0005 /* PsiTech RAD1 */
+#define PCI_PRODUCT_SGI_TIGON 0x0009 /* Tigon Gigabit Ethernet */
+
+/* SGS Thomson products */
+#define PCI_PRODUCT_SGSTHOMSON_2000 0x0008 /* STG 2000X */
+#define PCI_PRODUCT_SGSTHOMSON_1764 0x1746 /* STG 1764X */
+
+/* SiByte, Inc. products */
+#define PCI_PRODUCT_SIBYTE_SB1250_PCI 0x0001 /* BCM1250 PCI Host Bridge */
+#define PCI_PRODUCT_SIBYTE_SB1250_LDT 0x0002 /* BCM1250 HyperTransport Host Bridge */
+
+/* Sigma Designs products */
+#define PCI_PRODUCT_SIGMA_HOLLYWOODPLUS 0x8300 /* REALmagic Hollywood-Plus MPEG-2 Decoder */
+
+/* Silicon Integrated System products */
+#define PCI_PRODUCT_SIS_86C201 0x0001 /* 86C201 */
+#define PCI_PRODUCT_SIS_86C202 0x0002 /* 86C202 */
+#define PCI_PRODUCT_SIS_86C205 0x0005 /* 86C205 */
+#define PCI_PRODUCT_SIS_85C503 0x0008 /* 85C503 or 5597/5598 ISA bridge */
+#define PCI_PRODUCT_SIS_600PMC 0x0009 /* 600 Power Mngmt Controller */
+#define PCI_PRODUCT_SIS_5597_VGA 0x0200 /* 5597/5598 integrated VGA */
+#define PCI_PRODUCT_SIS_85C501 0x0406 /* 85C501 */
+#define PCI_PRODUCT_SIS_85C496 0x0496 /* 85C496 */
+#define PCI_PRODUCT_SIS_530HB 0x0530 /* 530 Host to PCI Bridge */
+#define PCI_PRODUCT_SIS_85C601 0x0601 /* 85C601 */
+#define PCI_PRODUCT_SIS_900 0x0900 /* SiS 900 10/100 Ethernet */
+#define PCI_PRODUCT_SIS_5597_IDE 0x5513 /* 5597/5598 IDE controller */
+#define PCI_PRODUCT_SIS_5597_HB 0x5597 /* 5597/5598 host bridge */
+#define PCI_PRODUCT_SIS_530VGA 0x6306 /* 530 GUI Accelerator+3D */
+#define PCI_PRODUCT_SIS_6326 0x6326 /* 6326 AGP VGA */
+#define PCI_PRODUCT_SIS_5597_USB 0x7001 /* 5597/5598 USB host controller */
+#define PCI_PRODUCT_SIS_7016 0x7016 /* SiS 7016 10/100 Ethernet */
+
+/* Silicon Motion products */
+#define PCI_PRODUCT_SILMOTION_LYNX_E 0x0810 /* Lynx E */
+
+/* SMC products */
+#define PCI_PRODUCT_SMC_37C665 0x1000 /* FDC 37C665 */
+#define PCI_PRODUCT_SMC_37C922 0x1001 /* FDC 37C922 */
+#define PCI_PRODUCT_SMC_83C170 0x0005 /* 83C170 (\"EPIC/100\") Fast Ethernet */
+#define PCI_PRODUCT_SMC_83C175 0x0006 /* 83C175 (\"EPIC/100\") Fast Ethernet */
+
+/* Solidum Systems Corporation */
+#define PCI_PRODUCT_SOLIDUM_AMD971 0x2000 /* SNP8023: AMD 971 */
+#define PCI_PRODUCT_SOLIDUM_CLASS802 0x8023 /* SNP8023: Classifier Engine */
+
+/* Sony products */
+#define PCI_PRODUCT_SONY_CXD1947A 0x8009 /* CXD1947A IEEE 1394 Host Controller */
+#define PCI_PRODUCT_SONY_CXD32222 0x8039 /* CXD3222 OHCI IEEE 1394 Host Controller */
+#define PCI_PRODUCT_SONY_MEMSTICK 0x808a /* Memory Stick I/F Controller */
+
+/* Sun Microsystems products */
+#define PCI_PRODUCT_SUN_EBUS 0x1000 /* PCIO Ebus2 */
+#define PCI_PRODUCT_SUN_HMENETWORK 0x1001 /* PCIO Happy Meal Ethernet */
+#define PCI_PRODUCT_SUN_SIMBA 0x5000 /* Simba PCI bridge */
+#define PCI_PRODUCT_SUN_MS_IIep 0x9000 /* microSPARC IIep PCI */
+#define PCI_PRODUCT_SUN_US_IIi 0xa000 /* UltraSPARC IIi PCI */
+
+/* Sundance Technology products */
+#define PCI_PRODUCT_SUNDANCETI_ST201 0x0201 /* ST201 10/100 Ethernet */
+
+/* Surecom Technology products */
+#define PCI_PRODUCT_SURECOM_NE34 0x0e34 /* NE-34 Ethernet */
+
+/* Symphony Labs products */
+#define PCI_PRODUCT_SYMPHONY_82C101 0x0001 /* 82C101 */
+#define PCI_PRODUCT_SYMPHONY_82C103 0x0103 /* 82C103 */
+#define PCI_PRODUCT_SYMPHONY_82C105 0x0105 /* 82C105 */
+#define PCI_PRODUCT_SYMPHONY2_82C101 0x0001 /* 82C101 */
+#define PCI_PRODUCT_SYMPHONY_83C553 0x0565 /* 83C553 PCI-ISA Bridge */
+
+/* Schneider & Koch (really SysKonnect) products */
+#define PCI_PRODUCT_SCHNEIDERKOCH_SKNET_FDDI 0x4000 /* SK-NET FDDI-xP */
+
+/* Tekram Technology products (1st PCI Vendor ID)*/
+#define PCI_PRODUCT_TEKRAM_DC290 0xdc29 /* DC-290(M) */
+
+/* Tekram Technology products (2nd PCI Vendor ID) */
+#define PCI_PRODUCT_TEKRAM2_DC690C 0x690c /* DC-690C */
+
+/* Texas Instruments products */
+#define PCI_PRODUCT_TI_TLAN 0x0500 /* TLAN */
+#define PCI_PRODUCT_TI_TVP4020 0x3d07 /* TVP4020 Permedia 2 */
+#define PCI_PRODUCT_TI_TSB12LV21 0x8000 /* TSB12LV21 IEEE 1394 Host Controller */
+#define PCI_PRODUCT_TI_TSB12LV22 0x8009 /* TSB12LV22 OHCI IEEE 1394 Host Controller */
+#define PCI_PRODUCT_TI_TSB12LV23 0x8019 /* TSB12LV23 OHCI IEEE 1394 Host Controller */
+#define PCI_PRODUCT_TI_TSB12LV26 0x8020 /* TSB12LV26 OHCI IEEE 1394 Host Controller */
+#define PCI_PRODUCT_TI_PCI1130 0xac12 /* PCI1130 PCI-CardBus Bridge */
+#define PCI_PRODUCT_TI_PCI1031 0xac13 /* PCI1031 PCI-PCMCIA Bridge */
+#define PCI_PRODUCT_TI_PCI1131 0xac15 /* PCI1131 PCI-CardBus Bridge */
+#define PCI_PRODUCT_TI_PCI1250 0xac16 /* PCI1250 PCI-CardBus Bridge */
+#define PCI_PRODUCT_TI_PCI1220 0xac17 /* PCI1220 PCI-CardBus Bridge */
+#define PCI_PRODUCT_TI_PCI1221 0xac19 /* PCI1221 PCI-CardBus Bridge */
+#define PCI_PRODUCT_TI_PCI1450 0xac1b /* PCI1450 PCI-CardBus Bridge */
+#define PCI_PRODUCT_TI_PCI1225 0xac1c /* PCI1225 PCI-CardBus Bridge */
+#define PCI_PRODUCT_TI_PCI1251 0xac1d /* PCI1251 PCI-CardBus Bridge */
+#define PCI_PRODUCT_TI_PCI1211 0xac1e /* PCI1211 PCI-CardBus Bridge */
+#define PCI_PRODUCT_TI_PCI1251B 0xac1f /* PCI1251B PCI-CardBus Bridge */
+#define PCI_PRODUCT_TI_PCI2030 0xac20 /* PCI2030 PCI-PCI Bridge */
+#define PCI_PRODUCT_TI_PCI1420 0xac51 /* PCI1420 PCI-CardBus Bridge */
+#define PCI_PRODUCT_TI_PCI1451 0xac52 /* PCI1451 PCI-CardBus Bridge */
+
+/* Toshiba America products */
+#define PCI_PRODUCT_TOSHIBA_R4X00 0x0009 /* R4x00 Host-PCI Bridge */
+#define PCI_PRODUCT_TOSHIBA_TC35856F 0x0020 /* TC35856F ATM (\"Meteor\") */
+
+/* Toshiba America Info Systems products */
+#define PCI_PRODUCT_TOSHIBA2_HOST 0x0601 /* Host Bridge/Controller */
+#define PCI_PRODUCT_TOSHIBA2_ISA 0x0602 /* ISA Bridge */
+#define PCI_PRODUCT_TOSHIBA2_ToPIC95 0x0603 /* ToPIC95 CardBus-PCI Bridge */
+#define PCI_PRODUCT_TOSHIBA2_ToPIC95B 0x060a /* ToPIC95B CardBus-PCI Bridge */
+#define PCI_PRODUCT_TOSHIBA2_ToPIC97 0x060f /* ToPIC97 CardBus-PCI Bridge */
+#define PCI_PRODUCT_TOSHIBA2_ToPIC100 0x0617 /* ToPIC100 CardBus-PCI Bridge */
+#define PCI_PRODUCT_TOSHIBA2_FIRO 0x0701 /* Fast Infrared Type O */
+
+/* Trident products */
+#define PCI_PRODUCT_TRIDENT_CYBERBLADE_I7 0x8420 /* CyberBlade i7 */
+#define PCI_PRODUCT_TRIDENT_TGUI_9320 0x9320 /* TGUI 9320 */
+#define PCI_PRODUCT_TRIDENT_TGUI_9350 0x9350 /* TGUI 9350 */
+#define PCI_PRODUCT_TRIDENT_TGUI_9360 0x9360 /* TGUI 9360 */
+#define PCI_PRODUCT_TRIDENT_CYBER_9397 0x9397 /* CYBER 9397 */
+#define PCI_PRODUCT_TRIDENT_CYBER_9397DVD 0x939a /* CYBER 9397DVD */
+#define PCI_PRODUCT_TRIDENT_CYBER_9525 0x9525 /* CYBER 9525 */
+#define PCI_PRODUCT_TRIDENT_TGUI_9420 0x9420 /* TGUI 9420 */
+#define PCI_PRODUCT_TRIDENT_TGUI_9440 0x9440 /* TGUI 9440 */
+#define PCI_PRODUCT_TRIDENT_TGUI_9660 0x9660 /* TGUI 9660 */
+#define PCI_PRODUCT_TRIDENT_TGUI_9680 0x9680 /* TGUI 9680 */
+#define PCI_PRODUCT_TRIDENT_TGUI_9682 0x9682 /* TGUI 9682 */
+
+/* Triones Technologies products */
+/* The 366 and 370 controllers have the same product ID */
+#define PCI_PRODUCT_TRIONES_HPT366 0x0004 /* HPT366/370 IDE Controller */
+
+/* TriTech Microelectronics products*/
+#define PCI_PRODUCT_TRITECH_TR25202 0xfc02 /* Pyramid3D TR25202 */
+
+/* Tseng Labs products */
+#define PCI_PRODUCT_TSENG_ET4000_W32P_A 0x3202 /* ET4000w32p rev A */
+#define PCI_PRODUCT_TSENG_ET4000_W32P_B 0x3205 /* ET4000w32p rev B */
+#define PCI_PRODUCT_TSENG_ET4000_W32P_C 0x3206 /* ET4000w32p rev C */
+#define PCI_PRODUCT_TSENG_ET4000_W32P_D 0x3207 /* ET4000w32p rev D */
+#define PCI_PRODUCT_TSENG_ET6000 0x3208 /* ET6000 */
+
+/* UMC products */
+#define PCI_PRODUCT_UMC_UM82C881 0x0001 /* UM82C881 486 Chipset */
+#define PCI_PRODUCT_UMC_UM82C886 0x0002 /* UM82C886 ISA Bridge */
+#define PCI_PRODUCT_UMC_UM8673F 0x0101 /* UM8673F EIDE Controller */
+#define PCI_PRODUCT_UMC_UM8881 0x0881 /* UM8881 HB4 486 PCI Chipset */
+#define PCI_PRODUCT_UMC_UM82C891 0x0891 /* UM82C891 */
+#define PCI_PRODUCT_UMC_UM886A 0x1001 /* UM886A */
+#define PCI_PRODUCT_UMC_UM8886BF 0x673a /* UM8886BF */
+#define PCI_PRODUCT_UMC_UM8710 0x8710 /* UM8710 */
+#define PCI_PRODUCT_UMC_UM8886 0x886a /* UM8886 */
+#define PCI_PRODUCT_UMC_UM8881F 0x8881 /* UM8881F PCI-Host bridge */
+#define PCI_PRODUCT_UMC_UM8886F 0x8886 /* UM8886F PCI-ISA bridge */
+#define PCI_PRODUCT_UMC_UM8886A 0x888a /* UM8886A */
+#define PCI_PRODUCT_UMC_UM8891A 0x8891 /* UM8891A */
+#define PCI_PRODUCT_UMC_UM9017F 0x9017 /* UM9017F */
+#define PCI_PRODUCT_UMC_UM8886N 0xe88a /* UM8886N */
+#define PCI_PRODUCT_UMC_UM8891N 0xe891 /* UM8891N */
+
+/* ULSI Systems products */
+#define PCI_PRODUCT_ULSI_US201 0x0201 /* US201 */
+
+/* US Robotics products */
+#define PCI_PRODUCT_USR_3CP5609 0x1008 /* 3CP5609 PCI 16550 Modem */
+
+/* V3 Semiconductor products */
+#define PCI_PRODUCT_V3_V292PBC 0x0292 /* V292PBC AMD290x0 Host-PCI Bridge */
+#define PCI_PRODUCT_V3_V960PBC 0x0960 /* V960PBC i960 Host-PCI Bridge */
+#define PCI_PRODUCT_V3_V96DPC 0xC960 /* V96DPC i960 (Dual) Host-PCI Bridge */
+
+/* VIA Technologies products, from http://www.via.com.tw/ */
+#define PCI_PRODUCT_VIATECH_VT8371_HB 0x0391 /* VT8371 (Apollo KX133) Host Bridge */
+#define PCI_PRODUCT_VIATECH_VT8501_MVP4 0x0501 /* VT8501 MVP4 System Controller */
+#define PCI_PRODUCT_VIATECH_VT82C505 0x0505 /* VT82C505 (Pluto) */
+#define PCI_PRODUCT_VIATECH_VT82C561 0x0561 /* VT82C561 */
+#define PCI_PRODUCT_VIATECH_VT82C586A_IDE 0x0571 /* VT82C586A IDE Controller */
+#define PCI_PRODUCT_VIATECH_VT82C576 0x0576 /* VT82C576 3V */
+#define PCI_PRODUCT_VIATECH_VT82C580VP 0x0585 /* VT82C580 (Apollo VP) Host-PCI Bridge */
+#define PCI_PRODUCT_VIATECH_VT82C586_ISA 0x0586 /* VT82C586 (Apollo VP) PCI-ISA Bridge */
+#define PCI_PRODUCT_VIATECH_VT82C595 0x0595 /* VT82C595 (Apollo VP2) Host-PCI Bridge */
+#define PCI_PRODUCT_VIATECH_VT82C596A 0x0596 /* VT82C596A (Apollo Pro) PCI-ISA Bridge */
+#define PCI_PRODUCT_VIATECH_VT82C597 0x0597 /* VT82C597 (Apollo VP3) Host-PCI Bridge */
+#define PCI_PRODUCT_VIATECH_VT82C598PCI 0x0598 /* VT82C598 (Apollo MVP3) Host-PCI */
+#define PCI_PRODUCT_VIATECH_VT82C686A_ISA 0x0686 /* VT82C686A (Apollo KX133) PCI-ISA Bridge */
+#define PCI_PRODUCT_VIATECH_VT82C691 0x0691 /* VT82C691 (Apollo Pro) Host-PCI */
+#define PCI_PRODUCT_VIATECH_VT82C693 0x0693 /* VT82C693 (Apollo Pro Plus) Host-PCI */
+#define PCI_PRODUCT_VIATECH_VT86C926 0x0926 /* VT86C926 Amazon PCI-Ethernet Controller */
+#define PCI_PRODUCT_VIATECH_VT82C570M 0x1000 /* VT82C570M (Apollo) Host-PCI Bridge */
+#define PCI_PRODUCT_VIATECH_VT82C570MV 0x1006 /* VT82C570M (Apollo) PCI-ISA Bridge */
+#define PCI_PRODUCT_VIATECH_VT82C586_IDE 0x1571 /* VT82C586 (Apollo VP) IDE Controller */
+#define PCI_PRODUCT_VIATECH_VT82C595_2 0x1595 /* VT82C595 (Apollo VP2) Host-PCI Bridge */
+#define PCI_PRODUCT_VIATECH_VT83C572 0x3038 /* VT83C572 USB Controller */
+#define PCI_PRODUCT_VIATECH_VT82C586_PWR 0x3040 /* VT82C586 (Apollo VP) Power Management Controller */
+#define PCI_PRODUCT_VIATECH_VT3043 0x3043 /* VT3043 (Rhine) 10/100 Ethernet */
+#define PCI_PRODUCT_VIATECH_VT82C686A_SMB 0x3057 /* VT82C686A SMBus Controller */
+#define PCI_PRODUCT_VIATECH_VT82C686A_AC97 0x3058 /* VT82C686A AC-97 Audio Controller */
+#define PCI_PRODUCT_VIATECH_VT82C686A_MC97 0x3068 /* VT82C686A MC-97 Modem Controller */
+#define PCI_PRODUCT_VIATECH_VT86C100A 0x6100 /* VT86C100A (Rhine-II) 10/100 Ethernet */
+#define PCI_PRODUCT_VIATECH_VT8371_PPB 0x8391 /* VT8371 (Apollo KX133) PCI-PCI Bridge */
+#define PCI_PRODUCT_VIATECH_VT8501AGP 0x8501 /* VT8501 PCI-AGP */
+#define PCI_PRODUCT_VIATECH_VT82C597AGP 0x8597 /* VT82C597 (Apollo VP3) PCI-AGP */
+#define PCI_PRODUCT_VIATECH_VT82C598AGP 0x8598 /* VT82C598 (Apollo MVP3) PCI-AGP */
+
+/* Vortex Computer Systems products */
+/* GDT_PCI */
+#define PCI_PRODUCT_VORTEX_GDT_60x0 0x0000 /* GDT6000/6020/6050 */
+#define PCI_PRODUCT_VORTEX_GDT_6000B 0x0001 /* GDT6000B/6010 */
+/* GDT_PCINEW */
+#define PCI_PRODUCT_VORTEX_GDT_6x10 0x0002 /* GDT6110/6510 */
+#define PCI_PRODUCT_VORTEX_GDT_6x20 0x0003 /* GDT6120/6520 */
+#define PCI_PRODUCT_VORTEX_GDT_6530 0x0004 /* GDT6530 */
+#define PCI_PRODUCT_VORTEX_GDT_6550 0x0005 /* GDT6550 */
+/* GDT_PCINEW, wide/ultra SCSI controllers */
+#define PCI_PRODUCT_VORTEX_GDT_6x17 0x0006 /* GDT6117/6517 */
+#define PCI_PRODUCT_VORTEX_GDT_6x27 0x0007 /* GDT6127/6527 */
+#define PCI_PRODUCT_VORTEX_GDT_6537 0x0008 /* GDT6537 */
+#define PCI_PRODUCT_VORTEX_GDT_6557 0x0009 /* GDT6557/6557-ECC */
+/* GDT_PCINEW, wide SCSI controllers */
+#define PCI_PRODUCT_VORTEX_GDT_6x15 0x0010 /* GDT6115/6515 */
+#define PCI_PRODUCT_VORTEX_GDT_6x25 0x0011 /* GDT6125/6525 */
+#define PCI_PRODUCT_VORTEX_GDT_6535 0x0012 /* GDT6535 */
+#define PCI_PRODUCT_VORTEX_GDT_6555 0x0013 /* GDT6555/6555-ECC */
+/* GDT_MPR, RP series, wide/ultra SCSI */
+#define PCI_PRODUCT_VORTEX_GDT_6x17RP 0x0100 /* GDT6117RP/GDT6517RP */
+#define PCI_PRODUCT_VORTEX_GDT_6x27RP 0x0101 /* GDT6127RP/GDT6527RP */
+#define PCI_PRODUCT_VORTEX_GDT_6537RP 0x0102 /* GDT6537RP */
+#define PCI_PRODUCT_VORTEX_GDT_6557RP 0x0103 /* GDT6557RP */
+/* GDT_MPR, RP series, narrow/ultra SCSI */
+#define PCI_PRODUCT_VORTEX_GDT_6x11RP 0x0104 /* GDT6111RP/GDT6511RP */
+#define PCI_PRODUCT_VORTEX_GDT_6x21RP 0x0105 /* GDT6121RP/GDT6521RP */
+/* GDT_MPR, RD series, wide/ultra SCSI */
+#define PCI_PRODUCT_VORTEX_GDT_6x17RD 0x0110 /* GDT6117RD/GDT6517RD */
+#define PCI_PRODUCT_VORTEX_GDT_6x27RD 0x0111 /* GDT6127RD/GDT6527RD */
+#define PCI_PRODUCT_VORTEX_GDT_6537RD 0x0112 /* GDT6537RD */
+#define PCI_PRODUCT_VORTEX_GDT_6557RD 0x0113 /* GDT6557RD */
+/* GDT_MPR, RD series, narrow/ultra SCSI */
+#define PCI_PRODUCT_VORTEX_GDT_6x11RD 0x0114 /* GDT6111RD/GDT6511RD */
+#define PCI_PRODUCT_VORTEX_GDT_6x21RD 0x0115 /* GDT6121RD/GDT6521RD */
+/* GDT_MPR, RD series, wide/ultra2 SCSI */
+#define PCI_PRODUCT_VORTEX_GDT_6x18RD 0x0118 /* GDT6118RD/GDT6518RD/GDT6618RD */
+#define PCI_PRODUCT_VORTEX_GDT_6x28RD 0x0119 /* GDT6128RD/GDT6528RD/GDT6628RD */
+#define PCI_PRODUCT_VORTEX_GDT_6x38RD 0x011A /* GDT6538RD/GDT6638RD */
+#define PCI_PRODUCT_VORTEX_GDT_6x58RD 0x011B /* GDT6558RD/GDT6658RD */
+/* GDT_MPR, RN series (64-bit PCI), wide/ultra2 SCSI */
+#define PCI_PRODUCT_VORTEX_GDT_7x18RN 0x0168 /* GDT7118RN/GDT7518RN/GDT7618RN */
+#define PCI_PRODUCT_VORTEX_GDT_7x28RN 0x0169 /* GDT7128RN/GDT7528RN/GDT7628RN */
+#define PCI_PRODUCT_VORTEX_GDT_7x38RN 0x016A /* GDT7538RN/GDT7638RN */
+#define PCI_PRODUCT_VORTEX_GDT_7x58RN 0x016B /* GDT7558RN/GDT7658RN */
+/* GDT_MPR, RD series, Fibre Channel */
+#define PCI_PRODUCT_VORTEX_GDT_6x19RD 0x0210 /* GDT6519RD/GDT6619RD */
+#define PCI_PRODUCT_VORTEX_GDT_6x29RD 0x0211 /* GDT6529RD/GDT6629RD */
+/* GDT_MPR, RN series (64-bit PCI), Fibre Channel */
+#define PCI_PRODUCT_VORTEX_GDT_7x19RN 0x0260 /* GDT7519RN/GDT7619RN */
+#define PCI_PRODUCT_VORTEX_GDT_7x29RN 0x0261 /* GDT7529RN/GDT7629RN */
+
+/* VLSI products */
+#define PCI_PRODUCT_VLSI_82C592 0x0005 /* 82C592 CPU Bridge */
+#define PCI_PRODUCT_VLSI_82C593 0x0006 /* 82C593 ISA Bridge */
+#define PCI_PRODUCT_VLSI_82C594 0x0007 /* 82C594 Wildcat System Controller */
+#define PCI_PRODUCT_VLSI_82C596597 0x0008 /* 82C596/597 Wildcat ISA Bridge */
+#define PCI_PRODUCT_VLSI_82C541 0x000c /* 82C541 */
+#define PCI_PRODUCT_VLSI_82C543 0x000d /* 82C543 */
+#define PCI_PRODUCT_VLSI_82C532 0x0101 /* 82C532 */
+#define PCI_PRODUCT_VLSI_82C534 0x0102 /* 82C534 */
+#define PCI_PRODUCT_VLSI_82C535 0x0104 /* 82C535 */
+#define PCI_PRODUCT_VLSI_82C147 0x0105 /* 82C147 */
+#define PCI_PRODUCT_VLSI_82C975 0x0200 /* 82C975 */
+#define PCI_PRODUCT_VLSI_82C925 0x0280 /* 82C925 */
+
+/* Weitek products */
+#define PCI_PRODUCT_WEITEK_P9000 0x9001 /* P9000 */
+#define PCI_PRODUCT_WEITEK_P9100 0x9100 /* P9100 */
+
+/* Western Digital products */
+#define PCI_PRODUCT_WD_WD33C193A 0x0193 /* WD33C193A */
+#define PCI_PRODUCT_WD_WD33C196A 0x0196 /* WD33C196A */
+#define PCI_PRODUCT_WD_WD33C197A 0x0197 /* WD33C197A */
+#define PCI_PRODUCT_WD_WD7193 0x3193 /* WD7193 */
+#define PCI_PRODUCT_WD_WD7197 0x3197 /* WD7197 */
+#define PCI_PRODUCT_WD_WD33C296A 0x3296 /* WD33C296A */
+#define PCI_PRODUCT_WD_WD34C296 0x4296 /* WD34C296 */
+#define PCI_PRODUCT_WD_90C 0xC24A /* 90C */
+
+/* Winbond Electronics products */
+#define PCI_PRODUCT_WINBOND_W83769F 0x0001 /* W83769F */
+#define PCI_PRODUCT_WINBOND_W89C840F 0x0840 /* W89C840F 10/100 Ethernet */
+#define PCI_PRODUCT_WINBOND_W89C940F 0x0940 /* W89C940F Ethernet */
+#define PCI_PRODUCT_WINBOND_W89C940F_1 0x5a5a /* W89C940F Ethernet */
+
+/* Xircom products */
+/* is the `-3' here just indicating revision 3, or is it really part
+ of the device name? */
+#define PCI_PRODUCT_XIRCOM_X3201_3 0x0002 /* X3201-3 Fast Ethernet Controller */
+/* this is the device id `indicating 21143 driver compatibility' */
+#define PCI_PRODUCT_XIRCOM_X3201_3_21143 0x0003 /* X3201-3 Fast Ethernet Controller (21143) */
+
+/* Yamaha products */
+#define PCI_PRODUCT_YAMAHA_YMF724 0x0004 /* 724 Audio */
+#define PCI_PRODUCT_YAMAHA_YMF740 0x000A /* 740 Audio */
+#define PCI_PRODUCT_YAMAHA_YMF740C 0x000C /* 740C (DS-1) Audio */
+#define PCI_PRODUCT_YAMAHA_YMF724F 0x000D /* 724F (DS-1) Audio */
+#define PCI_PRODUCT_YAMAHA_YMF744B 0x0010 /* 744 (DS-1S) Audio */
+#define PCI_PRODUCT_YAMAHA_YMF754 0x0012 /* 754 (DS-1E) Audio */
+
+/* Zeinet products */
+#define PCI_PRODUCT_ZEINET_1221 0x0001 /* 1221 */
+
+/* Ziatech products */
+#define PCI_PRODUCT_ZIATECH_ZT8905 0x8905 /* PCI-ST32 Bridge */
+
+/* Zoran products */
+#define PCI_PRODUCT_ZORAN_ZR36120 0x6120 /* Video Controller */
diff --git a/cfe/cfe/pci/pcidevs_data.h b/cfe/cfe/pci/pcidevs_data.h
new file mode 100644
index 0000000..1bdc7f4
--- /dev/null
+++ b/cfe/cfe/pci/pcidevs_data.h
@@ -0,0 +1,5873 @@
+/*
+ * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.
+ *
+ * generated from:
+ * pcidevs 2002/09/03 broadcom
+ */
+
+/*
+ * Copyright (c) 1995, 1996 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+static const struct pci_knowndev pci_knowndevs[] = {
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C985,
+ 0,
+ "3Com",
+ "3c985 Gigabit Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C590,
+ 0,
+ "3Com",
+ "3c590 Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C595TX,
+ 0,
+ "3Com",
+ "3c595-TX 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C595T4,
+ 0,
+ "3Com",
+ "3c595-T4 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C595MII,
+ 0,
+ "3Com",
+ "3c595-MII 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C900TPO,
+ 0,
+ "3Com",
+ "3c900-TPO Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C900COMBO,
+ 0,
+ "3Com",
+ "3c900-COMBO Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905TX,
+ 0,
+ "3Com",
+ "3c905-TX 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905T4,
+ 0,
+ "3Com",
+ "3c905-T4 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C900BTPO,
+ 0,
+ "3Com",
+ "3c900B-TPO Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C900BCOMBO,
+ 0,
+ "3Com",
+ "3c900B-COMBO Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C900BTPC,
+ 0,
+ "3Com",
+ "3c900B-TPC Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905BTX,
+ 0,
+ "3Com",
+ "3c905B-TX 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905BT4,
+ 0,
+ "3Com",
+ "3c905B-T4 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905BCOMBO,
+ 0,
+ "3Com",
+ "3c905B-COMBO 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905BFX,
+ 0,
+ "3Com",
+ "3c905B-FX 100 Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905CTX,
+ 0,
+ "3Com",
+ "3c905C-TX 10/100 Ethernet with mngmt",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C980SRV,
+ 0,
+ "3Com",
+ "3c980 Server Adapter 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C980CTXM,
+ 0,
+ "3Com",
+ "3c980C-TXM 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CR990TX97,
+ 0,
+ "3Com",
+ "3CR990-TX-97 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_3DFX, PCI_PRODUCT_3DFX_VOODOO,
+ 0,
+ "3Dfx Interactive",
+ "Voodoo",
+ },
+ {
+ PCI_VENDOR_3DFX, PCI_PRODUCT_3DFX_VOODOO2,
+ 0,
+ "3Dfx Interactive",
+ "Voodoo2",
+ },
+ {
+ PCI_VENDOR_3DFX, PCI_PRODUCT_3DFX_BANSHEE,
+ 0,
+ "3Dfx Interactive",
+ "Banshee",
+ },
+ {
+ PCI_VENDOR_3DFX, PCI_PRODUCT_3DFX_VOODOO3,
+ 0,
+ "3Dfx Interactive",
+ "Voodoo3",
+ },
+ {
+ PCI_VENDOR_3DLABS, PCI_PRODUCT_3DLABS_300SX,
+ 0,
+ "3D Labs",
+ "GLINT 300SX",
+ },
+ {
+ PCI_VENDOR_3DLABS, PCI_PRODUCT_3DLABS_500TX,
+ 0,
+ "3D Labs",
+ "GLINT 500TX",
+ },
+ {
+ PCI_VENDOR_3DLABS, PCI_PRODUCT_3DLABS_DELTA,
+ 0,
+ "3D Labs",
+ "GLINT DELTA",
+ },
+ {
+ PCI_VENDOR_3DLABS, PCI_PRODUCT_3DLABS_PERMEDIA,
+ 0,
+ "3D Labs",
+ "GLINT Permedia",
+ },
+ {
+ PCI_VENDOR_3DLABS, PCI_PRODUCT_3DLABS_500MX,
+ 0,
+ "3D Labs",
+ "GLINT 500MX",
+ },
+ {
+ PCI_VENDOR_3DLABS, PCI_PRODUCT_3DLABS_PERMEDI2,
+ 0,
+ "3D Labs",
+ "GLINT Permedia 2",
+ },
+ {
+ PCI_VENDOR_3WARE, PCI_PRODUCT_3WARE_ESCALADE,
+ 0,
+ "3ware",
+ "Escalade IDE RAID",
+ },
+ {
+ PCI_VENDOR_ACC, PCI_PRODUCT_ACC_2188,
+ 0,
+ "ACC Microelectronics",
+ "ACCM 2188 VL-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_ACC, PCI_PRODUCT_ACC_2051_HB,
+ 0,
+ "ACC Microelectronics",
+ "2051 PCI Single Chip Solution (host bridge)",
+ },
+ {
+ PCI_VENDOR_ACC, PCI_PRODUCT_ACC_2051_ISA,
+ 0,
+ "ACC Microelectronics",
+ "2051 PCI Single Chip Solution (ISA bridge)",
+ },
+ {
+ PCI_VENDOR_ACARD, PCI_PRODUCT_ACARD_AEC6710,
+ 0,
+ "Acard",
+ "AEC6710 SCSI",
+ },
+ {
+ PCI_VENDOR_ACARD, PCI_PRODUCT_ACARD_AEC6712UW,
+ 0,
+ "Acard",
+ "AEC6712UW SCSI",
+ },
+ {
+ PCI_VENDOR_ACARD, PCI_PRODUCT_ACARD_AEC6712U,
+ 0,
+ "Acard",
+ "AEC6712U SCSI",
+ },
+ {
+ PCI_VENDOR_ACARD, PCI_PRODUCT_ACARD_AEC6712S,
+ 0,
+ "Acard",
+ "AEC6712S SCSI",
+ },
+ {
+ PCI_VENDOR_ACARD, PCI_PRODUCT_ACARD_AEC6710D,
+ 0,
+ "Acard",
+ "AEC6710D SCSI",
+ },
+ {
+ PCI_VENDOR_ACARD, PCI_PRODUCT_ACARD_AEC6715UW,
+ 0,
+ "Acard",
+ "AEC6715UW SCSI",
+ },
+ {
+ PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_MPX5030,
+ 0,
+ "Accton Technology",
+ "MPX 5030/5038 Ethernet",
+ },
+ {
+ PCI_VENDOR_ACER, PCI_PRODUCT_ACER_M1435,
+ 0,
+ "Acer",
+ "M1435 VL-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M1445,
+ 0,
+ "Acer Labs",
+ "M1445 VL-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M1449,
+ 0,
+ "Acer Labs",
+ "M1449 PCI-ISA Bridge",
+ },
+ {
+ PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M1451,
+ 0,
+ "Acer Labs",
+ "M1451 Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M1461,
+ 0,
+ "Acer Labs",
+ "M1461 Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M1531,
+ 0,
+ "Acer Labs",
+ "M1531 Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M1541,
+ 0,
+ "Acer Labs",
+ "M1541 Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M1543,
+ 0,
+ "Acer Labs",
+ "M1543 PCI-ISA Bridge",
+ },
+ {
+ PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M3309,
+ 0,
+ "Acer Labs",
+ "M3309 MPEG Decoder",
+ },
+ {
+ PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M4803,
+ 0,
+ "Acer Labs",
+ "M4803",
+ },
+ {
+ PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M5229,
+ 0,
+ "Acer Labs",
+ "M5229 UDMA IDE Controller",
+ },
+ {
+ PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M5237,
+ 0,
+ "Acer Labs",
+ "M5237 USB Host Controller",
+ },
+ {
+ PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M7101,
+ 0,
+ "Acer Labs",
+ "M7101 Power Management Controller",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_AIC7850,
+ 0,
+ "Adaptec",
+ "AIC-7850",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_AIC7855,
+ 0,
+ "Adaptec",
+ "AIC-7855",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_AIC5900,
+ 0,
+ "Adaptec",
+ "AIC-5900 ATM",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_AIC5905,
+ 0,
+ "Adaptec",
+ "AIC-5905 ATM",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_AIC6915,
+ 0,
+ "Adaptec",
+ "AIC-6915 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_AIC7860,
+ 0,
+ "Adaptec",
+ "AIC-7860",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_APA1480,
+ 0,
+ "Adaptec",
+ "APA-1480 Ultra",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_2940AU,
+ 0,
+ "Adaptec",
+ "AHA-2940A Ultra",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_AIC7870,
+ 0,
+ "Adaptec",
+ "AIC-7870",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_2940,
+ 0,
+ "Adaptec",
+ "AHA-2940",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_3940,
+ 0,
+ "Adaptec",
+ "AHA-3940",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_3985,
+ 0,
+ "Adaptec",
+ "AHA-3985",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_2944,
+ 0,
+ "Adaptec",
+ "AHA-2944",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_AIC7895,
+ 0,
+ "Adaptec",
+ "AIC-7895 Ultra",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_AIC7880,
+ 0,
+ "Adaptec",
+ "AIC-7880 Ultra",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_2940U,
+ 0,
+ "Adaptec",
+ "AHA-2940 Ultra",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_3940U,
+ 0,
+ "Adaptec",
+ "AHA-3940 Ultra",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_389XU,
+ 0,
+ "Adaptec",
+ "AHA-389X Ultra",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_2944U,
+ 0,
+ "Adaptec",
+ "AHA-2944 Ultra",
+ },
+ {
+ PCI_VENDOR_ADP, PCI_PRODUCT_ADP_2940UP,
+ 0,
+ "Adaptec",
+ "AHA-2940 Ultra Pro",
+ },
+ {
+ PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_2940U2,
+ 0,
+ "Adaptec (2nd PCI Vendor ID)",
+ "AHA-2940 Ultra2",
+ },
+ {
+ PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_2930U2,
+ 0,
+ "Adaptec (2nd PCI Vendor ID)",
+ "AHA-2930 Ultra2",
+ },
+ {
+ PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_AIC7890,
+ 0,
+ "Adaptec (2nd PCI Vendor ID)",
+ "AIC-7890/1",
+ },
+ {
+ PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_3950U2B,
+ 0,
+ "Adaptec (2nd PCI Vendor ID)",
+ "AHA-3950 Ultra2",
+ },
+ {
+ PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_3950U2D,
+ 0,
+ "Adaptec (2nd PCI Vendor ID)",
+ "AHA-3950 Ultra2",
+ },
+ {
+ PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_AIC7896,
+ 0,
+ "Adaptec (2nd PCI Vendor ID)",
+ "AIC-7896/7",
+ },
+ {
+ PCI_VENDOR_ADDTRON, PCI_PRODUCT_ADDTRON_8139,
+ 0,
+ "Addtron Technology",
+ "8139 Ethernet",
+ },
+ {
+ PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AL981,
+ 0,
+ "ADMtek",
+ "ADMtek AL981 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_ADVSYS, PCI_PRODUCT_ADVSYS_1200A,
+ 0,
+ "Advanced System Products",
+ "",
+ },
+ {
+ PCI_VENDOR_ADVSYS, PCI_PRODUCT_ADVSYS_1200B,
+ 0,
+ "Advanced System Products",
+ "",
+ },
+ {
+ PCI_VENDOR_ADVSYS, PCI_PRODUCT_ADVSYS_ULTRA,
+ 0,
+ "Advanced System Products",
+ "ABP-930/40UA",
+ },
+ {
+ PCI_VENDOR_ADVSYS, PCI_PRODUCT_ADVSYS_WIDE,
+ 0,
+ "Advanced System Products",
+ "ABP-940UW",
+ },
+ {
+ PCI_VENDOR_ADVSYS, PCI_PRODUCT_ADVSYS_U2W,
+ 0,
+ "Advanced System Products",
+ "ASB-3940U2W",
+ },
+ {
+ PCI_VENDOR_ADVSYS, PCI_PRODUCT_ADVSYS_U3W,
+ 0,
+ "Advanced System Products",
+ "ASB-3940U3W",
+ },
+ {
+ PCI_VENDOR_ALLIANCE, PCI_PRODUCT_ALLIANCE_AT24,
+ 0,
+ "Alliance Semiconductor",
+ "AT24",
+ },
+ {
+ PCI_VENDOR_ALLIANCE, PCI_PRODUCT_ALLIANCE_AT25,
+ 0,
+ "Alliance Semiconductor",
+ "AT25",
+ },
+ {
+ PCI_VENDOR_ALTEON, PCI_PRODUCT_ALTEON_ACENIC,
+ 0,
+ "Alteon",
+ "ACEnic Gigabit Ethernet",
+ },
+ {
+ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PCNET_PCI,
+ 0,
+ "Advanced Micro Devices",
+ "79c970 PCnet-PCI LANCE Ethernet",
+ },
+ {
+ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PCNET_HOME,
+ 0,
+ "Advanced Micro Devices",
+ "79c978 PCnet-PCI Home",
+ },
+ {
+ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PCSCSI_PCI,
+ 0,
+ "Advanced Micro Devices",
+ "53c974 PCscsi-PCI SCSI",
+ },
+ {
+ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PCNETS_PCI,
+ 0,
+ "Advanced Micro Devices",
+ "79C974 PCnet-PCI Ethernet & SCSI",
+ },
+ {
+ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_SC751_SC,
+ 0,
+ "Advanced Micro Devices",
+ "AMD751 System Controller",
+ },
+ {
+ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_SC751_PPB,
+ 0,
+ "Advanced Micro Devices",
+ "AMD751 PCI-to-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PBC756_ISA,
+ 0,
+ "Advanced Micro Devices",
+ "AMD756 PCI-to-ISA Bridge",
+ },
+ {
+ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PBC756_IDE,
+ 0,
+ "Advanced Micro Devices",
+ "AMD756 IDE controller",
+ },
+ {
+ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PBC756_PMC,
+ 0,
+ "Advanced Micro Devices",
+ "AMD756 Power Management Controller",
+ },
+ {
+ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PBC756_USB,
+ 0,
+ "Advanced Micro Devices",
+ "AMD756 USB Host Controller",
+ },
+ {
+ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_HT7520,
+ 0,
+ "Advanced Micro Devices",
+ "(PLX) HT7520 PCIX Tunnel",
+ },
+ {
+ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_HT7520_PIC,
+ 0,
+ "Advanced Micro Devices",
+ "(PLX) HT7520 PCIX IOAPIC",
+ },
+ {
+ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD8151_AGP,
+ 0,
+ "Advanced Micro Devices",
+ "AMD8151 AGP Device",
+ },
+ {
+ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD8151,
+ 0,
+ "Advanced Micro Devices",
+ "AMD8151 HyperTransport-AGP Bridge",
+ },
+ {
+ PCI_VENDOR_API, PCI_PRODUCT_API_STURGEON,
+ 0,
+ "API Networks",
+ "AP1011 HyperTransport-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_BANDIT,
+ 0,
+ "Apple Computer",
+ "Bandit Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_GC,
+ 0,
+ "Apple Computer",
+ "Grand Central I/O Controller",
+ },
+ {
+ PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_CONTROL,
+ 0,
+ "Apple Computer",
+ "Control",
+ },
+ {
+ PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_PLANB,
+ 0,
+ "Apple Computer",
+ "PlanB",
+ },
+ {
+ PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_OHARE,
+ 0,
+ "Apple Computer",
+ "OHare I/O Controller",
+ },
+ {
+ PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_BANDIT2,
+ 0,
+ "Apple Computer",
+ "Bandit Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_HEATHROW,
+ 0,
+ "Apple Computer",
+ "MAC-IO I/O Controller (Heathrow)",
+ },
+ {
+ PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_PADDINGTON,
+ 0,
+ "Apple Computer",
+ "MAC-IO I/O Controller (Paddington)",
+ },
+ {
+ PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_KEYLARGO_USB,
+ 0,
+ "Apple Computer",
+ "KeyLargo USB Controller",
+ },
+ {
+ PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_UNINORTH1,
+ 0,
+ "Apple Computer",
+ "UniNorth Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_UNINORTH2,
+ 0,
+ "Apple Computer",
+ "UniNorth Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_UNINORTH_AGP,
+ 0,
+ "Apple Computer",
+ "UniNorth AGP Interface",
+ },
+ {
+ PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_GMAC,
+ 0,
+ "Apple Computer",
+ "GMAC Ethernet",
+ },
+ {
+ PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_KEYLARGO,
+ 0,
+ "Apple Computer",
+ "MAC-IO I/O Controller (KeyLargo)",
+ },
+ {
+ PCI_VENDOR_ARC, PCI_PRODUCT_ARC_1000PV,
+ 0,
+ "ARC Logic",
+ "1000PV",
+ },
+ {
+ PCI_VENDOR_ARC, PCI_PRODUCT_ARC_2000PV,
+ 0,
+ "ARC Logic",
+ "2000PV",
+ },
+ {
+ PCI_VENDOR_ARC, PCI_PRODUCT_ARC_2000MT,
+ 0,
+ "ARC Logic",
+ "2000MT",
+ },
+ {
+ PCI_VENDOR_ASIX, PCI_PRODUCT_ASIX_AX88140A,
+ 0,
+ "ASIX Electronics",
+ "AX88140A 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH32,
+ 0,
+ "ATI Technologies",
+ "Mach32",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_CT,
+ 0,
+ "ATI Technologies",
+ "Mach64 CT",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_CX,
+ 0,
+ "ATI Technologies",
+ "Mach64 CX",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_ET,
+ 0,
+ "ATI Technologies",
+ "Mach64 ET",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_VT,
+ 0,
+ "ATI Technologies",
+ "Mach64 VT",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_B,
+ 0,
+ "ATI Technologies",
+ "Mach64 B",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_GB,
+ 0,
+ "ATI Technologies",
+ "Mach64 GB",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_GD,
+ 0,
+ "ATI Technologies",
+ "Mach64 GD",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_GI,
+ 0,
+ "ATI Technologies",
+ "Mach64 GI",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_GP,
+ 0,
+ "ATI Technologies",
+ "Mach64 GP",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_GQ,
+ 0,
+ "ATI Technologies",
+ "Mach64 GQ",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_GT,
+ 0,
+ "ATI Technologies",
+ "Mach64 GT",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_GU,
+ 0,
+ "ATI Technologies",
+ "Mach64 GU",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_GV,
+ 0,
+ "ATI Technologies",
+ "Mach64 GV",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_GW,
+ 0,
+ "ATI Technologies",
+ "Mach64 GW",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_GX,
+ 0,
+ "ATI Technologies",
+ "Mach64 GX",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_GZ,
+ 0,
+ "ATI Technologies",
+ "Mach64 GZ",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_LB,
+ 0,
+ "ATI Technologies",
+ "Mach64 LB",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_LD,
+ 0,
+ "ATI Technologies",
+ "Mach64 LD",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_LG,
+ 0,
+ "ATI Technologies",
+ "Mach64 LG",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_LI,
+ 0,
+ "ATI Technologies",
+ "Mach64 LI",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_LM,
+ 0,
+ "ATI Technologies",
+ "Mach64 LM",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_LP,
+ 0,
+ "ATI Technologies",
+ "Mach64 LP",
+ },
+ {
+ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_MACH64_LR,
+ 0,
+ "ATI Technologies",
+ "Mach64 LR",
+ },
+ {
+ PCI_VENDOR_AURAVISION, PCI_PRODUCT_AURAVISION_VXP524,
+ 0,
+ "Auravision",
+ "VxP524 PCI Video Processor",
+ },
+ {
+ PCI_VENDOR_AUREAL, PCI_PRODUCT_AUREAL_AU8820,
+ 0,
+ "Aureal Semiconductor",
+ "AU8820 Vortex Digital Audio Processor",
+ },
+ {
+ PCI_VENDOR_AMCIRCUITS, PCI_PRODUCT_AMCIRCUITS_S5933,
+ 0,
+ "Applied Micro Circuits",
+ "S5933 PCI Matchmaker",
+ },
+ {
+ PCI_VENDOR_AMCIRCUITS, PCI_PRODUCT_AMCIRCUITS_LANAI,
+ 0,
+ "Applied Micro Circuits",
+ "Myrinet LANai Interface",
+ },
+ {
+ PCI_VENDOR_AMCIRCUITS, PCI_PRODUCT_AMCIRCUITS_S5920,
+ 0,
+ "Applied Micro Circuits",
+ "S5920 PCI Target",
+ },
+ {
+ PCI_VENDOR_ATRONICS, PCI_PRODUCT_ATRONICS_IDE_2015PL,
+ 0,
+ "Atronics",
+ "IDE-2015PL",
+ },
+ {
+ PCI_VENDOR_AVANCE, PCI_PRODUCT_AVANCE_AVL2301,
+ 0,
+ "Avance Logic",
+ "AVL2301",
+ },
+ {
+ PCI_VENDOR_AVANCE, PCI_PRODUCT_AVANCE_AVG2302,
+ 0,
+ "Avance Logic",
+ "AVG2302",
+ },
+ {
+ PCI_VENDOR_AVANCE2, PCI_PRODUCT_AVANCE2_ALG2301,
+ 0,
+ "Avance Logic (2nd PCI Vendor ID)",
+ "ALG2301",
+ },
+ {
+ PCI_VENDOR_AVANCE2, PCI_PRODUCT_AVANCE2_ALG2302,
+ 0,
+ "Avance Logic (2nd PCI Vendor ID)",
+ "ALG2302",
+ },
+ {
+ PCI_VENDOR_CCUBE, PCI_PRODUCT_CCUBE_CINEMASTER,
+ 0,
+ "C-Cube Microsystems",
+ "Cinemaster C 3.0 DVD Decoder",
+ },
+ {
+ PCI_VENDOR_AVM, PCI_PRODUCT_AVM_FRITZ_CARD,
+ 0,
+ "AVM",
+ "Fritz! Card ISDN Interface",
+ },
+ {
+ PCI_VENDOR_BIT3, PCI_PRODUCT_BIT3_PCIVME617,
+ 0,
+ "Bit3 Computer Corp.",
+ "PCI-VME Interface Mod. 617",
+ },
+ {
+ PCI_VENDOR_BIT3, PCI_PRODUCT_BIT3_PCIVME618,
+ 0,
+ "Bit3 Computer Corp.",
+ "PCI-VME Interface Mod. 618",
+ },
+ {
+ PCI_VENDOR_BIT3, PCI_PRODUCT_BIT3_PCIVME2706,
+ 0,
+ "Bit3 Computer Corp.",
+ "PCI-VME Interface Mod. 2706",
+ },
+ {
+ PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4211,
+ 0,
+ "Broadcom",
+ "BCM4211 iLine10 Controller",
+ },
+ {
+ PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4212,
+ 0,
+ "Broadcom",
+ "BCM4212 V.90 Modem",
+ },
+ {
+ PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5700,
+ 0,
+ "Broadcom",
+ "BCM5700 10/100/1000 Ethernet",
+ },
+ {
+ PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5701,
+ 0,
+ "Broadcom",
+ "BCM5701 10/100/1000 Ethernet",
+ },
+ {
+ PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5702,
+ 0,
+ "Broadcom",
+ "BCM5702 10/100/1000 Ethernet",
+ },
+ {
+ PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5703,
+ 0,
+ "Broadcom",
+ "BCM5703 10/100/1000 Ethernet",
+ },
+ {
+ PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5705,
+ 0,
+ "Broadcom",
+ "BCM5705 10/100/1000 Ethernet",
+ },
+ {
+ PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5820,
+ 0,
+ "Broadcom",
+ "BCM5820 eCommerce Processor",
+ },
+ {
+ PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5821,
+ 0,
+ "Broadcom",
+ "BCM5821 Super-eCommerce Processor",
+ },
+ {
+ PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5850,
+ 0,
+ "Broadcom",
+ "BCM5850 SSL/TLS Protocol Processor",
+ },
+ {
+ PCI_VENDOR_BROOKTREE, PCI_PRODUCT_BROOKTREE_BT848,
+ 0,
+ "Brooktree",
+ "Bt848 Video Capture",
+ },
+ {
+ PCI_VENDOR_BROOKTREE, PCI_PRODUCT_BROOKTREE_BT849,
+ 0,
+ "Brooktree",
+ "Bt849 Video Capture",
+ },
+ {
+ PCI_VENDOR_BROOKTREE, PCI_PRODUCT_BROOKTREE_BT878,
+ 0,
+ "Brooktree",
+ "Bt878 Video Capture",
+ },
+ {
+ PCI_VENDOR_BROOKTREE, PCI_PRODUCT_BROOKTREE_BT879,
+ 0,
+ "Brooktree",
+ "Bt879 Video Capture",
+ },
+ {
+ PCI_VENDOR_BUSLOGIC, PCI_PRODUCT_BUSLOGIC_MULTIMASTER_NC,
+ 0,
+ "BusLogic",
+ "MultiMaster NC",
+ },
+ {
+ PCI_VENDOR_BUSLOGIC, PCI_PRODUCT_BUSLOGIC_MULTIMASTER,
+ 0,
+ "BusLogic",
+ "MultiMaster",
+ },
+ {
+ PCI_VENDOR_BUSLOGIC, PCI_PRODUCT_BUSLOGIC_FLASHPOINT,
+ 0,
+ "BusLogic",
+ "FlashPoint",
+ },
+ {
+ PCI_VENDOR_C4T, PCI_PRODUCT_C4T_GPPCI,
+ 0,
+ "c't Magazin",
+ "GPPCI",
+ },
+ {
+ PCI_VENDOR_CHIPS, PCI_PRODUCT_CHIPS_64310,
+ 0,
+ "Chips and Technologies",
+ "64310",
+ },
+ {
+ PCI_VENDOR_CHIPS, PCI_PRODUCT_CHIPS_65545,
+ 0,
+ "Chips and Technologies",
+ "65545",
+ },
+ {
+ PCI_VENDOR_CHIPS, PCI_PRODUCT_CHIPS_65548,
+ 0,
+ "Chips and Technologies",
+ "65548",
+ },
+ {
+ PCI_VENDOR_CHIPS, PCI_PRODUCT_CHIPS_65550,
+ 0,
+ "Chips and Technologies",
+ "65550",
+ },
+ {
+ PCI_VENDOR_CHIPS, PCI_PRODUCT_CHIPS_65554,
+ 0,
+ "Chips and Technologies",
+ "65554",
+ },
+ {
+ PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_GD7548,
+ 0,
+ "Cirrus Logic",
+ "CL-GD7548",
+ },
+ {
+ PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_GD5430,
+ 0,
+ "Cirrus Logic",
+ "CL-GD5430",
+ },
+ {
+ PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_GD5434_4,
+ 0,
+ "Cirrus Logic",
+ "CL-GD5434-4",
+ },
+ {
+ PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_GD5434_8,
+ 0,
+ "Cirrus Logic",
+ "CL-GD5434-8",
+ },
+ {
+ PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_GD5436,
+ 0,
+ "Cirrus Logic",
+ "CL-GD5436",
+ },
+ {
+ PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_GD5446,
+ 0,
+ "Cirrus Logic",
+ "CL-GD5446",
+ },
+ {
+ PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_GD5480,
+ 0,
+ "Cirrus Logic",
+ "CL-GD5480",
+ },
+ {
+ PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_PD6729,
+ 0,
+ "Cirrus Logic",
+ "CL-PD6729",
+ },
+ {
+ PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_PD6832,
+ 0,
+ "Cirrus Logic",
+ "CL-PD6832 PCI-CardBus Bridge",
+ },
+ {
+ PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_PD6833,
+ 0,
+ "Cirrus Logic",
+ "CL-PD6833 PCI-CardBus Bridge",
+ },
+ {
+ PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_GD7542,
+ 0,
+ "Cirrus Logic",
+ "CL-GD7542",
+ },
+ {
+ PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_GD7543,
+ 0,
+ "Cirrus Logic",
+ "CL-GD7543",
+ },
+ {
+ PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_GD7541,
+ 0,
+ "Cirrus Logic",
+ "CL-GD7541",
+ },
+ {
+ PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_CD4400,
+ 0,
+ "Cirrus Logic",
+ "CL-CD4400 Communications Controller",
+ },
+ {
+ PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CS4610,
+ 0,
+ "Cirrus Logic",
+ "CS4610 SoundFusion Audio Accelerator",
+ },
+ {
+ PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CS4280,
+ 0,
+ "Cirrus Logic",
+ "CS4280 CrystalClear Audio Interface",
+ },
+ {
+ PCI_VENDOR_CMDTECH, PCI_PRODUCT_CMDTECH_640,
+ 0,
+ "CMD Technology",
+ "PCI0640",
+ },
+ {
+ PCI_VENDOR_CMDTECH, PCI_PRODUCT_CMDTECH_642,
+ 0,
+ "CMD Technology",
+ "PCI0642",
+ },
+ {
+ PCI_VENDOR_CMDTECH, PCI_PRODUCT_CMDTECH_643,
+ 0,
+ "CMD Technology",
+ "PCI0643",
+ },
+ {
+ PCI_VENDOR_CMDTECH, PCI_PRODUCT_CMDTECH_646,
+ 0,
+ "CMD Technology",
+ "PCI0646",
+ },
+ {
+ PCI_VENDOR_CMDTECH, PCI_PRODUCT_CMDTECH_647,
+ 0,
+ "CMD Technology",
+ "PCI0647",
+ },
+ {
+ PCI_VENDOR_CMDTECH, PCI_PRODUCT_CMDTECH_648,
+ 0,
+ "CMD Technology",
+ "PCI0648",
+ },
+ {
+ PCI_VENDOR_CMDTECH, PCI_PRODUCT_CMDTECH_649,
+ 0,
+ "CMD Technology",
+ "PCI0649",
+ },
+ {
+ PCI_VENDOR_CMDTECH, PCI_PRODUCT_CMDTECH_650A,
+ 0,
+ "CMD Technology",
+ "PCI0650A",
+ },
+ {
+ PCI_VENDOR_CMDTECH, PCI_PRODUCT_CMDTECH_670,
+ 0,
+ "CMD Technology",
+ "USB0670",
+ },
+ {
+ PCI_VENDOR_CMDTECH, PCI_PRODUCT_CMDTECH_673,
+ 0,
+ "CMD Technology",
+ "USB0673",
+ },
+ {
+ PCI_VENDOR_CMEDIA, PCI_PRODUCT_CMEDIA_CMI8338A,
+ 0,
+ "C-Media Electronics Inc",
+ "CMI8338A PCI Audio Device",
+ },
+ {
+ PCI_VENDOR_CMEDIA, PCI_PRODUCT_CMEDIA_CMI8338B,
+ 0,
+ "C-Media Electronics Inc",
+ "CMI8338B PCI Audio Device",
+ },
+ {
+ PCI_VENDOR_CMEDIA, PCI_PRODUCT_CMEDIA_CMI8738,
+ 0,
+ "C-Media Electronics Inc",
+ "CMI8738/C3DX PCI Audio Device",
+ },
+ {
+ PCI_VENDOR_CMEDIA, PCI_PRODUCT_CMEDIA_HSP56,
+ 0,
+ "C-Media Electronics Inc",
+ "HSP56 Audiomodem Riser",
+ },
+ {
+ PCI_VENDOR_COGENT, PCI_PRODUCT_COGENT_EM110TX,
+ 0,
+ "Cogent Data Technologies",
+ "EX110TX PCI Fast Ethernet Adapter",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_PCI_EISA_BRIDGE,
+ 0,
+ "Compaq",
+ "PCI-EISA Bridge",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_PCI_ISA_BRIDGE,
+ 0,
+ "Compaq",
+ "PCI-ISA Bridge",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX1,
+ 0,
+ "Compaq",
+ "Triflex Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX2,
+ 0,
+ "Compaq",
+ "Triflex Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_QVISION_V0,
+ 0,
+ "Compaq",
+ "QVision",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_QVISION_1280P,
+ 0,
+ "Compaq",
+ "QVision 1280/p",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_QVISION_V2,
+ 0,
+ "Compaq",
+ "QVision",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX4,
+ 0,
+ "Compaq",
+ "Triflex Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_USB,
+ 0,
+ "Compaq",
+ "USB Controller",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_SMART2P,
+ 0,
+ "Compaq",
+ "SMART2P RAID",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_N100TX,
+ 0,
+ "Compaq",
+ "Netelligent 10/100 TX",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_N10T,
+ 0,
+ "Compaq",
+ "Netelligent 10 T",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_IntNF3P,
+ 0,
+ "Compaq",
+ "Integrated NetFlex 3/P",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_DPNet100TX,
+ 0,
+ "Compaq",
+ "Dual Port Netelligent 10/100 TX",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_IntPL100TX,
+ 0,
+ "Compaq",
+ "ProLiant Integrated Netelligent 10/100 TX",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_DP4000,
+ 0,
+ "Compaq",
+ "Deskpro 4000 5233MMX",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_NF3P_BNC,
+ 0,
+ "Compaq",
+ "NetFlex 3/P w/ BNC",
+ },
+ {
+ PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_NF3P,
+ 0,
+ "Compaq",
+ "NetFlex 3/P",
+ },
+ {
+ PCI_VENDOR_COMPEX, PCI_PRODUCT_COMPEX_NE2KETHER,
+ 0,
+ "Compex",
+ "Ethernet",
+ },
+ {
+ PCI_VENDOR_COMPEX, PCI_PRODUCT_COMPEX_RL100ATX,
+ 0,
+ "Compex",
+ "RL100-ATX 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_COMPEX, PCI_PRODUCT_COMPEX_RL100TX,
+ 0,
+ "Compex",
+ "RL100-TX 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_CONEXANT, PCI_PRODUCT_CONEXANT_SOFTK56,
+ 0,
+ "Conexant Systems",
+ "SoftK56 PCI Software Modem",
+ },
+ {
+ PCI_VENDOR_CONTAQ, PCI_PRODUCT_CONTAQ_82C599,
+ 0,
+ "Contaq Microsystems",
+ "82C599 PCI-VLB Bridge",
+ },
+ {
+ PCI_VENDOR_CONTAQ, PCI_PRODUCT_CONTAQ_82C693,
+ 0,
+ "Contaq Microsystems",
+ "82C693 PCI-ISA Bridge",
+ },
+ {
+ PCI_VENDOR_COROLLARY, PCI_PRODUCT_COROLLARY_CBUSII_PCIB,
+ 0,
+ "Corrollary",
+ "\"C-Bus II\"-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_CREATIVELABS, PCI_PRODUCT_CREATIVELABS_SBLIVE,
+ 0,
+ "Creative Labs",
+ "SBLive! EMU 10000",
+ },
+ {
+ PCI_VENDOR_CREATIVELABS, PCI_PRODUCT_CREATIVELABS_SBJOY,
+ 0,
+ "Creative Labs",
+ "PCI Gameport Joystick",
+ },
+ {
+ PCI_VENDOR_CREATIVELABS, PCI_PRODUCT_CREATIVELABS_EV1938,
+ 0,
+ "Creative Labs",
+ "Ectiva 1938",
+ },
+ {
+ PCI_VENDOR_CYCLADES, PCI_PRODUCT_CYCLADES_CYCLOMY_1,
+ 0,
+ "Cyclades",
+ "Cyclom-Y below 1M",
+ },
+ {
+ PCI_VENDOR_CYCLADES, PCI_PRODUCT_CYCLADES_CYCLOMY_2,
+ 0,
+ "Cyclades",
+ "Cyclom-Y above 1M",
+ },
+ {
+ PCI_VENDOR_CYCLADES, PCI_PRODUCT_CYCLADES_CYCLOM4Y_1,
+ 0,
+ "Cyclades",
+ "Cyclom-4Y below 1M",
+ },
+ {
+ PCI_VENDOR_CYCLADES, PCI_PRODUCT_CYCLADES_CYCLOM4Y_2,
+ 0,
+ "Cyclades",
+ "Cyclom-4Y above 1M",
+ },
+ {
+ PCI_VENDOR_CYCLADES, PCI_PRODUCT_CYCLADES_CYCLOM8Y_1,
+ 0,
+ "Cyclades",
+ "Cyclom-8Y below 1M",
+ },
+ {
+ PCI_VENDOR_CYCLADES, PCI_PRODUCT_CYCLADES_CYCLOM8Y_2,
+ 0,
+ "Cyclades",
+ "Cyclom-8Y above 1M",
+ },
+ {
+ PCI_VENDOR_CYCLADES, PCI_PRODUCT_CYCLADES_CYCLOMZ_1,
+ 0,
+ "Cyclades",
+ "Cyclom-Z below 1M",
+ },
+ {
+ PCI_VENDOR_CYCLADES, PCI_PRODUCT_CYCLADES_CYCLOMZ_2,
+ 0,
+ "Cyclades",
+ "Cyclom-Z above 1M",
+ },
+ {
+ PCI_VENDOR_DAVICOM, PCI_PRODUCT_DAVICOM_DM9102,
+ 0,
+ "Davicom Semiconductor",
+ "Davicom DM9102 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21050,
+ 0,
+ "Digital Equipment",
+ "DECchip 21050 PCI-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21040,
+ 0,
+ "Digital Equipment",
+ "DECchip 21040 Ethernet",
+ },
+ {
+ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21030,
+ 0,
+ "Digital Equipment",
+ "DECchip 21030 (\"TGA\")",
+ },
+ {
+ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_NVRAM,
+ 0,
+ "Digital Equipment",
+ "Zephyr NV-RAM",
+ },
+ {
+ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_KZPSA,
+ 0,
+ "Digital Equipment",
+ "KZPSA",
+ },
+ {
+ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21140,
+ 0,
+ "Digital Equipment",
+ "DECchip 21140 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_PBXGB,
+ 0,
+ "Digital Equipment",
+ "TGA2",
+ },
+ {
+ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_DEFPA,
+ 0,
+ "Digital Equipment",
+ "DEFPA",
+ },
+ {
+ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21041,
+ 0,
+ "Digital Equipment",
+ "DECchip 21041 Ethernet",
+ },
+ {
+ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_DGLPB,
+ 0,
+ "Digital Equipment",
+ "DGLPB (\"OPPO\")",
+ },
+ {
+ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21142,
+ 0,
+ "Digital Equipment",
+ "DECchip 21142/21143 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21052,
+ 0,
+ "Digital Equipment",
+ "DECchip 21052 PCI-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21150,
+ 0,
+ "Digital Equipment",
+ "DECchip 21150 PCI-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21152,
+ 0,
+ "Digital Equipment",
+ "DECchip 21152 PCI-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21153,
+ 0,
+ "Digital Equipment",
+ "DECchip 21153 PCI-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21154,
+ 0,
+ "Digital Equipment",
+ "DECchip 21154 PCI-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_DEC, PCI_PRODUCT_DEC_CPQ42XX,
+ 0,
+ "Digital Equipment",
+ "Compaq SMART RAID 42xx",
+ },
+ {
+ PCI_VENDOR_DELTA, PCI_PRODUCT_DELTA_8139,
+ 0,
+ "Delta Electronics",
+ "8139 Ethernet",
+ },
+ {
+ PCI_VENDOR_DIAMOND, PCI_PRODUCT_DIAMOND_VIPER,
+ 0,
+ "Diamond Computer Systems",
+ "Viper/PCI",
+ },
+ {
+ PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DFE550TX,
+ 0,
+ "D-Link Systems",
+ "DFE-550TX 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_DPT, PCI_PRODUCT_DPT_SC_RAID,
+ 0,
+ "Distributed Processing Technology",
+ "SmartCache/SmartRAID",
+ },
+ {
+ PCI_VENDOR_DPT, PCI_PRODUCT_DPT_RAID_I2O,
+ 0,
+ "Distributed Processing Technology",
+ "SmartRAID (I2O)",
+ },
+ {
+ PCI_VENDOR_DPT, PCI_PRODUCT_DPT_MEMCTLR,
+ 0,
+ "Distributed Processing Technology",
+ "Memory Controller",
+ },
+ {
+ PCI_VENDOR_DOLPHIN, PCI_PRODUCT_DOLPHIN_PCISCI,
+ 0,
+ "Dolphin Interconnect Solutions",
+ "PCI-SCI Bridge",
+ },
+ {
+ PCI_VENDOR_DOMEX, PCI_PRODUCT_DOMEX_PCISCSI,
+ 0,
+ "Domex",
+ "DMX-3191D",
+ },
+ {
+ PCI_VENDOR_ELSA, PCI_PRODUCT_ELSA_QS1PCI,
+ 0,
+ "Elsa",
+ "QuickStep 1000 ISDN card",
+ },
+ {
+ PCI_VENDOR_EMULEX, PCI_PRODUCT_EMULEX_LPPFC,
+ 0,
+ "Emulex",
+ "\"Light Pulse\" FibreChannel adapter",
+ },
+ {
+ PCI_VENDOR_ENSONIQ, PCI_PRODUCT_ENSONIQ_AUDIOPCI,
+ 0,
+ "Ensoniq",
+ "AudioPCI",
+ },
+ {
+ PCI_VENDOR_ENSONIQ, PCI_PRODUCT_ENSONIQ_AUDIOPCI97,
+ 0,
+ "Ensoniq",
+ "AudioPCI 97",
+ },
+ {
+ PCI_VENDOR_ENSONIQ, PCI_PRODUCT_ENSONIQ_CT5880,
+ 0,
+ "Ensoniq",
+ "CT5880",
+ },
+ {
+ PCI_VENDOR_EPIGRAM, PCI_PRODUCT_EPIGRAM_BCM4210,
+ 0,
+ "Epigram",
+ "BCM4210 iLine10 Controller",
+ },
+ {
+ PCI_VENDOR_ESSENTIAL, PCI_PRODUCT_ESSENTIAL_RR_HIPPI,
+ 0,
+ "Essential Communications",
+ "RoadRunner HIPPI Interface",
+ },
+ {
+ PCI_VENDOR_ESSENTIAL, PCI_PRODUCT_ESSENTIAL_RR_GIGE,
+ 0,
+ "Essential Communications",
+ "RoadRunner Gig-E Interface",
+ },
+ {
+ PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_MAESTRO1,
+ 0,
+ "ESS Technology Inc",
+ "Maestro 1 PCI Audio Accelerator",
+ },
+ {
+ PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_MAESTRO2,
+ 0,
+ "ESS Technology Inc",
+ "Maestro 2 PCI Audio Accelerator",
+ },
+ {
+ PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_SOLO1,
+ 0,
+ "ESS Technology Inc",
+ "Solo-1 PCI AudioDrive",
+ },
+ {
+ PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_MAESTRO2E,
+ 0,
+ "ESS Technology Inc",
+ "Maestro 2E PCI Audio Accelerator",
+ },
+ {
+ PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_MAESTRO3,
+ 0,
+ "ESS Technology Inc",
+ "Maestro 3 PCI Audio Accelerator",
+ },
+ {
+ PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_MAESTRO3MODEM,
+ 0,
+ "ESS Technology Inc",
+ "Maestro 3 Modem",
+ },
+ {
+ PCI_VENDOR_ESSTECH2, PCI_PRODUCT_ESSTECH2_MAESTRO1,
+ 0,
+ "ESS Technology Inc",
+ "Maestro 1 PCI Audio Accelerator",
+ },
+ {
+ PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6832,
+ 0,
+ "O2 Micro Inc",
+ "OZ6832 CardBus Controller",
+ },
+ {
+ PCI_VENDOR_ES, PCI_PRODUCT_ES_FREEDOM,
+ 0,
+ "Evans & Sutherland",
+ "Freedom PCI-GBus Interface",
+ },
+ {
+ PCI_VENDOR_FORE, PCI_PRODUCT_FORE_PCA200,
+ 0,
+ "FORE Systems",
+ "ATM PCA-200",
+ },
+ {
+ PCI_VENDOR_FORE, PCI_PRODUCT_FORE_PCA200E,
+ 0,
+ "FORE Systems",
+ "ATM PCA-200e",
+ },
+ {
+ PCI_VENDOR_FORTEMEDIA, PCI_PRODUCT_FORTEMEDIA_FM801,
+ 0,
+ "Forte Media",
+ "Forte Media 801 Sound",
+ },
+ {
+ PCI_VENDOR_FUTUREDOMAIN, PCI_PRODUCT_FUTUREDOMAIN_TMC_18C30,
+ 0,
+ "Future Domain",
+ "TMC-18C30 (36C70)",
+ },
+ {
+ PCI_VENDOR_EFFICIENTNETS, PCI_PRODUCT_EFFICIENTNETS_ENI155PF,
+ 0,
+ "Efficent Networks",
+ "155P-MF1 ATM (FPGA)",
+ },
+ {
+ PCI_VENDOR_EFFICIENTNETS, PCI_PRODUCT_EFFICIENTNETS_ENI155PA,
+ 0,
+ "Efficent Networks",
+ "155P-MF1 ATM (ASIC)",
+ },
+ {
+ PCI_VENDOR_EFFICIENTNETS, PCI_PRODUCT_EFFICIENTNETS_ENI25P,
+ 0,
+ "Efficent Networks",
+ "SpeedStream ENI-25p",
+ },
+ {
+ PCI_VENDOR_EFFICIENTNETS, PCI_PRODUCT_EFFICIENTNETS_SS3000,
+ 0,
+ "Efficent Networks",
+ "SpeedStream 3000",
+ },
+ {
+ PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_GT64010A,
+ 0,
+ "Galileo Technology",
+ "GT-64010A System Controller",
+ },
+ {
+ PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_GT64115,
+ 0,
+ "Galileo Technology",
+ "GT-64115 System Controller",
+ },
+ {
+ PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_GT64011,
+ 0,
+ "Galileo Technology",
+ "GT-64011 System Controller",
+ },
+ {
+ PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_GT64120,
+ 0,
+ "Galileo Technology",
+ "GT-64120 System Controller",
+ },
+ {
+ PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_GT64130,
+ 0,
+ "Galileo Technology",
+ "GT-64130 System Controller",
+ },
+ {
+ PCI_VENDOR_HP, PCI_PRODUCT_HP_J2585A,
+ 0,
+ "Hewlett-Packard",
+ "J2585A",
+ },
+ {
+ PCI_VENDOR_IBM, PCI_PRODUCT_IBM_MCABRIDGE,
+ 0,
+ "IBM",
+ "MCA Bridge",
+ },
+ {
+ PCI_VENDOR_IBM, PCI_PRODUCT_IBM_ALTALITE,
+ 0,
+ "IBM",
+ "CPU Bridge - Alta Lite",
+ },
+ {
+ PCI_VENDOR_IBM, PCI_PRODUCT_IBM_ALTAMP,
+ 0,
+ "IBM",
+ "CPU Bridge - Alta MP",
+ },
+ {
+ PCI_VENDOR_IBM, PCI_PRODUCT_IBM_ISABRIDGE,
+ 0,
+ "IBM",
+ "ISA Bridge w/PnP",
+ },
+ {
+ PCI_VENDOR_IBM, PCI_PRODUCT_IBM_CPUBRIDGE,
+ 0,
+ "IBM",
+ "CPU Bridge",
+ },
+ {
+ PCI_VENDOR_IBM, PCI_PRODUCT_IBM_LANSTREAMER,
+ 0,
+ "IBM",
+ "Auto LANStreamer",
+ },
+ {
+ PCI_VENDOR_IBM, PCI_PRODUCT_IBM_GXT150P,
+ 0,
+ "IBM",
+ "GXT-150P 2D Accelerator",
+ },
+ {
+ PCI_VENDOR_IBM, PCI_PRODUCT_IBM_MCABRIDGE2,
+ 0,
+ "IBM",
+ "MCA Bridge",
+ },
+ {
+ PCI_VENDOR_IBM, PCI_PRODUCT_IBM_82351,
+ 0,
+ "IBM",
+ "82351 PCI-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_IBM, PCI_PRODUCT_IBM_SERVERAID,
+ 0,
+ "IBM",
+ "ServeRAID",
+ },
+ {
+ PCI_VENDOR_IBM, PCI_PRODUCT_IBM_OLYMPIC,
+ 0,
+ "IBM",
+ "Token Ring",
+ },
+ {
+ PCI_VENDOR_IBM, PCI_PRODUCT_IBM_MIAMI,
+ 0,
+ "IBM",
+ "Miami/PCI",
+ },
+ {
+ PCI_VENDOR_IBM, PCI_PRODUCT_IBM_TURBOWAYS25,
+ 0,
+ "IBM",
+ "Turboways 25 ATM",
+ },
+ {
+ PCI_VENDOR_IBM, PCI_PRODUCT_IBM_MPIC2,
+ 0,
+ "IBM",
+ "MPIC-II",
+ },
+ {
+ PCI_VENDOR_IDT, PCI_PRODUCT_IDT_77201,
+ 0,
+ "IDT",
+ "77201/77211 ATM (\"NICStAR\")",
+ },
+ {
+ PCI_VENDOR_INITIO, PCI_PRODUCT_INITIO_I920,
+ 0,
+ "Initio",
+ "INIC-920 SCSI",
+ },
+ {
+ PCI_VENDOR_INITIO, PCI_PRODUCT_INITIO_I940,
+ 0,
+ "Initio",
+ "INIC-940 SCSI",
+ },
+ {
+ PCI_VENDOR_INITIO, PCI_PRODUCT_INITIO_I935,
+ 0,
+ "Initio",
+ "INIC-935 SCSI",
+ },
+ {
+ PCI_VENDOR_INITIO, PCI_PRODUCT_INITIO_I950,
+ 0,
+ "Initio",
+ "INIC-950 SCSI",
+ },
+ {
+ PCI_VENDOR_IMS, PCI_PRODUCT_IMS_8849,
+ 0,
+ "Integrated Micro Solutions",
+ "8849",
+ },
+ {
+ PCI_VENDOR_IMS, PCI_PRODUCT_IMS_TT128M,
+ 0,
+ "Integrated Micro Solutions",
+ "TwinTurbo 128M",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PCEB,
+ 0,
+ "Intel",
+ "82375EB/SB PCI-EISA Bridge (PCEB)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_CDC,
+ 0,
+ "Intel",
+ "82424ZX Cache and DRAM controller (CDC)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_SIO,
+ 0,
+ "Intel",
+ "82378ZB System I/O (SIO)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82426EX,
+ 0,
+ "Intel",
+ "82426EX PCI-to-ISA Bridge (PCIB)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PCMC,
+ 0,
+ "Intel",
+ "82434LX/NX PCI, Cache and Memory Controller (PCMC)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_IN_BUSINESS,
+ 0,
+ "Intel",
+ "InBusiness Fast Ethernet LAN Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82559ER,
+ 0,
+ "Intel",
+ "82559ER Fast Ethernet LAN Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82092AA,
+ 0,
+ "Intel",
+ "82092AA IDE controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_SAA7116,
+ 0,
+ "Intel",
+ "SAA7116",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82596,
+ 0,
+ "Intel",
+ "82596 LAN Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_EEPRO100,
+ 0,
+ "Intel",
+ "EE Pro 100 10/100 Fast Ethernet",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_EEPRO100S,
+ 0,
+ "Intel",
+ "EE Pro 100 Smart 10/100 Fast Ethernet",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82557,
+ 0,
+ "Intel",
+ "82557 Fast Ethernet LAN Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82437FX,
+ 0,
+ "Intel",
+ "82437FX System Controller (TSC)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371FB_ISA,
+ 0,
+ "Intel",
+ "82371FB PCI-to-ISA Bridge (PIIX)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371FB_IDE,
+ 0,
+ "Intel",
+ "82371FB IDE controller (PIIX)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371MX,
+ 0,
+ "Intel",
+ "82371MX Mobile PCI I/O IDE Xcelerator (MPIIX)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82437MX,
+ 0,
+ "Intel",
+ "82437MX Mobile System Controller (MTSC)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82441FX,
+ 0,
+ "Intel",
+ "82441FX PCI and Memory Controller (PMC)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82380AB,
+ 0,
+ "Intel",
+ "82380AB Mobile PCI-to-ISA Bridge (MISA)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82380FB,
+ 0,
+ "Intel",
+ "82380FB Mobile PCI-to-PCI Bridge (MPCI2)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82439HX,
+ 0,
+ "Intel",
+ "82439HX System Controller (TXC)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AA_LPC,
+ 0,
+ "Intel",
+ "82801AA LPC Interface Bridge",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AA_IDE,
+ 0,
+ "Intel",
+ "82801AA IDE Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AA_USB,
+ 0,
+ "Intel",
+ "82801AA USB Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AA_SMB,
+ 0,
+ "Intel",
+ "82801AA SMBus Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AA_ACA,
+ 0,
+ "Intel",
+ "82801AA AC-97 Audio Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AA_ACM,
+ 0,
+ "Intel",
+ "82801AA AC-97 PCI Modem",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AA_HPB,
+ 0,
+ "Intel",
+ "82801AA Hub-to-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AB_LPC,
+ 0,
+ "Intel",
+ "82801AB LPC Interface Bridge",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AB_IDE,
+ 0,
+ "Intel",
+ "82801AB IDE Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AB_USB,
+ 0,
+ "Intel",
+ "82801AB USB Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AB_SMB,
+ 0,
+ "Intel",
+ "82801AB SMBus Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AB_ACA,
+ 0,
+ "Intel",
+ "82801AB AC-97 Audio Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AB_ACM,
+ 0,
+ "Intel",
+ "82801AB AC-97 PCI Modem",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AB_HPB,
+ 0,
+ "Intel",
+ "82801AB Hub-to-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_LPC,
+ 0,
+ "Intel",
+ "82801BA LPC Interface Bridge",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_USB1,
+ 0,
+ "Intel",
+ "82801BA USB Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_SMB,
+ 0,
+ "Intel",
+ "82801BA SMBus Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_USB2,
+ 0,
+ "Intel",
+ "82801BA USB Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_ACA,
+ 0,
+ "Intel",
+ "82801BA AC-97 Audio Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_ACM,
+ 0,
+ "Intel",
+ "82801BA AC-97 PCI Modem",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_LAN,
+ 0,
+ "Intel",
+ "82801BA LAN Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_IDE,
+ 0,
+ "Intel",
+ "82801BA IDE Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_HPB,
+ 0,
+ "Intel",
+ "82801BA Hub-to-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371SB_ISA,
+ 0,
+ "Intel",
+ "82371SB PCI-to-ISA Bridge (PIIX3)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371SB_IDE,
+ 0,
+ "Intel",
+ "82371SB IDE Interface (PIIX3)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371SB_USB,
+ 0,
+ "Intel",
+ "82371SB USB Host Controller (PIIX3)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82437VX,
+ 0,
+ "Intel",
+ "82437VX System Controller (TVX)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82439TX,
+ 0,
+ "Intel",
+ "82439TX System Controller (MTXC)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371AB_ISA,
+ 0,
+ "Intel",
+ "82371AB PCI-to-ISA Bridge (PIIX4)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371AB_IDE,
+ 0,
+ "Intel",
+ "82371AB IDE controller (PIIX4)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371AB_USB,
+ 0,
+ "Intel",
+ "82371AB USB Host Controller (PIIX4)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371AB_PMC,
+ 0,
+ "Intel",
+ "82371AB Power Management Controller (PIIX4)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82810_MCH,
+ 0,
+ "Intel",
+ "82810 Memory Controller Hub",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82810_GC,
+ 0,
+ "Intel",
+ "82810 Graphics Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82810_DC100_MCH,
+ 0,
+ "Intel",
+ "82810-DC100 Memory Controller Hub",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82810_DC100_GC,
+ 0,
+ "Intel",
+ "82810-DC100 Graphics Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82810E_MCH,
+ 0,
+ "Intel",
+ "82810E Memory Controller Hub",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82810E_GC,
+ 0,
+ "Intel",
+ "82810E Graphics Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82443LX,
+ 0,
+ "Intel",
+ "82443LX PCI AGP Controller (PAC)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82443LX_AGP,
+ 0,
+ "Intel",
+ "82443LX AGP Interface (PAC)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82443BX,
+ 0,
+ "Intel",
+ "82443BX Host Bridge/Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82443BX_AGP,
+ 0,
+ "Intel",
+ "82443BX AGP Interface",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82443BX_NOAGP,
+ 0,
+ "Intel",
+ "82443BX Host Bridge/Controller (AGP disabled)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82440MX,
+ 0,
+ "Intel",
+ "82440MX Host Bridge/Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82440MX_ACA,
+ 0,
+ "Intel",
+ "82440MX AC-97 Audio Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82440MX_ISA,
+ 0,
+ "Intel",
+ "82440MX PCI-to-ISA Bridge",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82440MX_IDE,
+ 0,
+ "Intel",
+ "82440MX IDE Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82440MX_USB,
+ 0,
+ "Intel",
+ "82440MX USB Host Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82440MX_PMC,
+ 0,
+ "Intel",
+ "82440MX Power Management Controller",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I740,
+ 0,
+ "Intel",
+ "i740 Graphics Accelerator",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PCI450_PB,
+ 0,
+ "Intel",
+ "82454KX/GX PCI Bridge (PB)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PCI450_MC,
+ 0,
+ "Intel",
+ "82451KX/GX Memory Controller (MC)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82451NX_MIOC,
+ 0,
+ "Intel",
+ "82451NX Memory & I/O Controller (MIOC)",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82451NX_PXB,
+ 0,
+ "Intel",
+ "82451NX PCI Expander Bridge (PXB)",
+ },
+ {
+ PCI_VENDOR_INTERGRAPH, PCI_PRODUCT_INTERGRAPH_4D50T,
+ 0,
+ "Intergraph",
+ "Powerstorm 4D50T",
+ },
+ {
+ PCI_VENDOR_ITT, PCI_PRODUCT_ITT_AGX016,
+ 0,
+ "I. T. T.",
+ "AGX016",
+ },
+ {
+ PCI_VENDOR_ITT, PCI_PRODUCT_ITT_ITT3204,
+ 0,
+ "I. T. T.",
+ "ITT3204 MPEG Decoder",
+ },
+ {
+ PCI_VENDOR_KTI, PCI_PRODUCT_KTI_NE2KETHER,
+ 0,
+ "KTI",
+ "Ethernet",
+ },
+ {
+ PCI_VENDOR_LMC, PCI_PRODUCT_LMC_HSSI,
+ 0,
+ "LAN Media Corporation",
+ "HSSI Interface",
+ },
+ {
+ PCI_VENDOR_LMC, PCI_PRODUCT_LMC_DS3,
+ 0,
+ "LAN Media Corporation",
+ "DS3 Interface",
+ },
+ {
+ PCI_VENDOR_LMC, PCI_PRODUCT_LMC_SSI,
+ 0,
+ "LAN Media Corporation",
+ "SSI",
+ },
+ {
+ PCI_VENDOR_LEADTEK, PCI_PRODUCT_LEADTEK_S3_805,
+ 0,
+ "LeadTek Research",
+ "S3 805",
+ },
+ {
+ PCI_VENDOR_LINEARSYS, PCI_PRODUCT_LINEARSYS_DVB_TX,
+ 0,
+ "Linear Systems",
+ "DVB Transmitter",
+ },
+ {
+ PCI_VENDOR_LINEARSYS, PCI_PRODUCT_LINEARSYS_DVB_RX,
+ 0,
+ "Linear Systems",
+ "DVB Receiver",
+ },
+ {
+ PCI_VENDOR_LITEON, PCI_PRODUCT_LITEON_82C168,
+ 0,
+ "Lite-On Communications",
+ "82C168/82C169 (PNIC) 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_LITEON, PCI_PRODUCT_LITEON_82C115,
+ 0,
+ "Lite-On Communications",
+ "82C115 (PNIC II) 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0440,
+ 0,
+ "AT&T Microelectronics",
+ "K56flex DSVD LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0441,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0442,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0443,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0444,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0445,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0446,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0447,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0448,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0449,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_044A,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_044B,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_044C,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_044D,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_044E,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0450,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0451,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0452,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0453,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0454,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0455,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0456,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0457,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0458,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_0459,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_LTMODEM_045A,
+ 0,
+ "AT&T Microelectronics",
+ "LTMODEM",
+ },
+ {
+ PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_USBHC,
+ 0,
+ "AT&T Microelectronics",
+ "USB Host Controller",
+ },
+ {
+ PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX98713,
+ 0,
+ "Macronix",
+ "MX98713 (PMAC) 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX987x5,
+ 0,
+ "Macronix",
+ "MX987x5 (PMAC) 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_MADGE, PCI_PRODUCT_MADGE_COLLAGE25,
+ 0,
+ "Madge Networks",
+ "Collage 25 ATM adapter",
+ },
+ {
+ PCI_VENDOR_MADGE, PCI_PRODUCT_MADGE_COLLAGE155,
+ 0,
+ "Madge Networks",
+ "Collage 155 ATM adapter",
+ },
+ {
+ PCI_VENDOR_MATROX, PCI_PRODUCT_MATROX_ATLAS,
+ 0,
+ "Matrox",
+ "MGA PX2085 (\"Atlas\")",
+ },
+ {
+ PCI_VENDOR_MATROX, PCI_PRODUCT_MATROX_MILLENNIUM,
+ 0,
+ "Matrox",
+ "MGA Millennium 2064W",
+ },
+ {
+ PCI_VENDOR_MATROX, PCI_PRODUCT_MATROX_MYSTIQUE,
+ 0,
+ "Matrox",
+ "MGA Mystique 1064SG",
+ },
+ {
+ PCI_VENDOR_MATROX, PCI_PRODUCT_MATROX_MILLENNIUM2,
+ 0,
+ "Matrox",
+ "MGA Millennium II 2164W",
+ },
+ {
+ PCI_VENDOR_MATROX, PCI_PRODUCT_MATROX_MILLENNIUM2_AGP,
+ 0,
+ "Matrox",
+ "MGA Millennium II 2164WA-B AG",
+ },
+ {
+ PCI_VENDOR_MATROX, PCI_PRODUCT_MATROX_G200_PCI,
+ 0,
+ "Matrox",
+ "MGA G200 PCI",
+ },
+ {
+ PCI_VENDOR_MATROX, PCI_PRODUCT_MATROX_G200_AGP,
+ 0,
+ "Matrox",
+ "MGA G200 AGP",
+ },
+ {
+ PCI_VENDOR_MATROX, PCI_PRODUCT_MATROX_G400_AGP,
+ 0,
+ "Matrox",
+ "MGA G400 AGP",
+ },
+ {
+ PCI_VENDOR_MATROX, PCI_PRODUCT_MATROX_IMPRESSION,
+ 0,
+ "Matrox",
+ "MGA Impression",
+ },
+ {
+ PCI_VENDOR_MATROX, PCI_PRODUCT_MATROX_G100_PCI,
+ 0,
+ "Matrox",
+ "MGA G100 PCI",
+ },
+ {
+ PCI_VENDOR_MATROX, PCI_PRODUCT_MATROX_G100_AGP,
+ 0,
+ "Matrox",
+ "MGA G100 AGP",
+ },
+ {
+ PCI_VENDOR_MOT, PCI_PRODUCT_MOT_MPC105,
+ 0,
+ "Motorola",
+ "MPC105 \"Eagle\" Host Bridge",
+ },
+ {
+ PCI_VENDOR_MOT, PCI_PRODUCT_MOT_MPC106,
+ 0,
+ "Motorola",
+ "MPC106 \"Grackle\" Host Bridge",
+ },
+ {
+ PCI_VENDOR_MYLEX, PCI_PRODUCT_MYLEX_960P,
+ 0,
+ "Mylex",
+ "DAC960P RAID controller",
+ },
+ {
+ PCI_VENDOR_MUTECH, PCI_PRODUCT_MUTECH_MV1000,
+ 0,
+ "Mutech",
+ "MV1000",
+ },
+ {
+ PCI_VENDOR_NETVIN, PCI_PRODUCT_NETVIN_5000,
+ 0,
+ "NetVin",
+ "5000 Ethernet",
+ },
+ {
+ PCI_VENDOR_NEWBRIDGE, PCI_PRODUCT_NEWBRIDGE_CA91CX42,
+ 0,
+ "Newbridge Microsystems / Tundra Semiconductor",
+ "Universe VME bridge",
+ },
+ {
+ PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83810,
+ 0,
+ "National Semiconductor",
+ "DP83810 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815,
+ 0,
+ "National Semiconductor",
+ "DP83815 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_NS, PCI_PRODUCT_NS_NS87410,
+ 0,
+ "National Semiconductor",
+ "NS87410",
+ },
+ {
+ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_810,
+ 0,
+ "Symbios Logic",
+ "53c810",
+ },
+ {
+ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_820,
+ 0,
+ "Symbios Logic",
+ "53c820",
+ },
+ {
+ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_825,
+ 0,
+ "Symbios Logic",
+ "53c825",
+ },
+ {
+ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_815,
+ 0,
+ "Symbios Logic",
+ "53c815",
+ },
+ {
+ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_810AP,
+ 0,
+ "Symbios Logic",
+ "53c810AP",
+ },
+ {
+ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_860,
+ 0,
+ "Symbios Logic",
+ "53c860",
+ },
+ {
+ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_896,
+ 0,
+ "Symbios Logic",
+ "53c896",
+ },
+ {
+ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_895,
+ 0,
+ "Symbios Logic",
+ "53c895",
+ },
+ {
+ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_885,
+ 0,
+ "Symbios Logic",
+ "53c885",
+ },
+ {
+ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_875,
+ 0,
+ "Symbios Logic",
+ "53c875",
+ },
+ {
+ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_1510,
+ 0,
+ "Symbios Logic",
+ "53c1510",
+ },
+ {
+ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_875J,
+ 0,
+ "Symbios Logic",
+ "53c875J",
+ },
+ {
+ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_PE_GNIC,
+ 0,
+ "Symbios Logic",
+ "Packet Engines G-NIC Ethernet",
+ },
+ {
+ PCI_VENDOR_NEC, PCI_PRODUCT_NEC_USB,
+ 0,
+ "NEC",
+ "USB Host Controller",
+ },
+ {
+ PCI_VENDOR_NEC, PCI_PRODUCT_NEC_POWERVR2,
+ 0,
+ "NEC",
+ "PowerVR PCX2",
+ },
+ {
+ PCI_VENDOR_NEC, PCI_PRODUCT_NEC_PD72872,
+ 0,
+ "NEC",
+ "uPD72872 IEEE 1394 OHCI Host Controller",
+ },
+ {
+ PCI_VENDOR_NEC, PCI_PRODUCT_NEC_PD72870,
+ 0,
+ "NEC",
+ "uPD72870 IEEE 1394 OHCI Host Controller",
+ },
+ {
+ PCI_VENDOR_NEC, PCI_PRODUCT_NEC_PD72871,
+ 0,
+ "NEC",
+ "uPD72871 IEEE 1394 OHCI Host Controller",
+ },
+ {
+ PCI_VENDOR_NEOMAGIC, PCI_PRODUCT_NEOMAGIC_NMMG128ZV,
+ 0,
+ "Neomagic",
+ "MagicGraph 128ZV",
+ },
+ {
+ PCI_VENDOR_NEOMAGIC, PCI_PRODUCT_NEOMAGIC_NMMG2160,
+ 0,
+ "Neomagic",
+ "MagicGraph 128XD",
+ },
+ {
+ PCI_VENDOR_NEOMAGIC, PCI_PRODUCT_NEOMAGIC_NMMM256AV_VGA,
+ 0,
+ "Neomagic",
+ "MagicMedia 256AV VGA",
+ },
+ {
+ PCI_VENDOR_NEOMAGIC, PCI_PRODUCT_NEOMAGIC_NMMM256ZX_VGA,
+ 0,
+ "Neomagic",
+ "MagicMedia 256ZX VGA",
+ },
+ {
+ PCI_VENDOR_NEOMAGIC, PCI_PRODUCT_NEOMAGIC_NMMM256AV_AU,
+ 0,
+ "Neomagic",
+ "MagicMedia 256AV Audio",
+ },
+ {
+ PCI_VENDOR_NEOMAGIC, PCI_PRODUCT_NEOMAGIC_NMMM256ZX_AU,
+ 0,
+ "Neomagic",
+ "MagicMedia 256ZX Audio",
+ },
+ {
+ PCI_VENDOR_NETGEAR, PCI_PRODUCT_NETGEAR_GA620,
+ 0,
+ "Netgear",
+ "GA620 Gigabit Ethernet",
+ },
+ {
+ PCI_VENDOR_NEXGEN, PCI_PRODUCT_NEXGEN_NX82C501,
+ 0,
+ "NexGen Microsystems",
+ "NX82C501 Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_NKK, PCI_PRODUCT_NKK_NDR4600,
+ 0,
+ "NKK Corporation",
+ "NDR4600 Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_NUMBER9, PCI_PRODUCT_NUMBER9_I128,
+ 0,
+ "Number 9 Computer Company",
+ "Imagine-128",
+ },
+ {
+ PCI_VENDOR_NUMBER9, PCI_PRODUCT_NUMBER9_I128_2,
+ 0,
+ "Number 9 Computer Company",
+ "Imagine-128 II",
+ },
+ {
+ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_RIVATNT,
+ 0,
+ "Nvidia Corporation",
+ "RIVA TNT",
+ },
+ {
+ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_RIVATNT2,
+ 0,
+ "Nvidia Corporation",
+ "RIVA TNT2",
+ },
+ {
+ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_RIVATNT2U,
+ 0,
+ "Nvidia Corporation",
+ "RIVA TNT2 Ultra",
+ },
+ {
+ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_VANTA,
+ 0,
+ "Nvidia Corporation",
+ "Vanta",
+ },
+ {
+ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_RIVATNT2M64,
+ 0,
+ "Nvidia Corporation",
+ "RIVA TNT2 Model 64",
+ },
+ {
+ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_ALADDINTNT2,
+ 0,
+ "Nvidia Corporation",
+ "Aladdin TNT2",
+ },
+ {
+ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_GEFORCE256,
+ 0,
+ "Nvidia Corporation",
+ "GeForce 256",
+ },
+ {
+ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_GEFORCEDDR,
+ 0,
+ "Nvidia Corporation",
+ "GeForce DDR",
+ },
+ {
+ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_QUADRO,
+ 0,
+ "Nvidia Corporation",
+ "Quadro",
+ },
+ {
+ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_GEFORCE2,
+ 0,
+ "Nvidia Corporation",
+ "GeForce2 GTS",
+ },
+ {
+ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_GEFORCE2DDR,
+ 0,
+ "Nvidia Corporation",
+ "GeForce2 GTS (DDR)",
+ },
+ {
+ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_GEFORCE2BR,
+ 0,
+ "Nvidia Corporation",
+ "GeForce2 GTS",
+ },
+ {
+ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_QUADRO2,
+ 0,
+ "Nvidia Corporation",
+ "Quadro2",
+ },
+ {
+ PCI_VENDOR_NVIDIA_SGS, PCI_PRODUCT_NVIDIA_SGS_RIVA128,
+ 0,
+ "Nvidia Corporation & SGS Thomson Microelectric",
+ "Riva 128",
+ },
+ {
+ PCI_VENDOR_OAKTECH, PCI_PRODUCT_OAKTECH_OTI1007,
+ 0,
+ "Oak Technology",
+ "OTI107",
+ },
+ {
+ PCI_VENDOR_OLICOM, PCI_PRODUCT_OLICOM_OC2183,
+ 0,
+ "Olicom",
+ "Olicom OC-2183/2185 Ethernet",
+ },
+ {
+ PCI_VENDOR_OLICOM, PCI_PRODUCT_OLICOM_OC2325,
+ 0,
+ "Olicom",
+ "Olicom OC-2325 Ethernet",
+ },
+ {
+ PCI_VENDOR_OLICOM, PCI_PRODUCT_OLICOM_OC2326,
+ 0,
+ "Olicom",
+ "Olicom OC-2326 10/100-TX Ethernet",
+ },
+ {
+ PCI_VENDOR_OPTI, PCI_PRODUCT_OPTI_82C557,
+ 0,
+ "Opti",
+ "82C557",
+ },
+ {
+ PCI_VENDOR_OPTI, PCI_PRODUCT_OPTI_82C558,
+ 0,
+ "Opti",
+ "82C558",
+ },
+ {
+ PCI_VENDOR_OPTI, PCI_PRODUCT_OPTI_82C568,
+ 0,
+ "Opti",
+ "82C568",
+ },
+ {
+ PCI_VENDOR_OPTI, PCI_PRODUCT_OPTI_82D568,
+ 0,
+ "Opti",
+ "82D568",
+ },
+ {
+ PCI_VENDOR_OPTI, PCI_PRODUCT_OPTI_82C621,
+ 0,
+ "Opti",
+ "82C621",
+ },
+ {
+ PCI_VENDOR_OPTI, PCI_PRODUCT_OPTI_82C822,
+ 0,
+ "Opti",
+ "82C822",
+ },
+ {
+ PCI_VENDOR_OPTI, PCI_PRODUCT_OPTI_RM861HA,
+ 0,
+ "Opti",
+ "RM861HA",
+ },
+ {
+ PCI_VENDOR_OPTI, PCI_PRODUCT_OPTI_82C700,
+ 0,
+ "Opti",
+ "82C700",
+ },
+ {
+ PCI_VENDOR_OPTI, PCI_PRODUCT_OPTI_82C701,
+ 0,
+ "Opti",
+ "82C701",
+ },
+ {
+ PCI_VENDOR_PCTECH, PCI_PRODUCT_PCTECH_RZ1000,
+ 0,
+ "PC Technology",
+ "RZ1000",
+ },
+ {
+ PCI_VENDOR_PLX, PCI_PRODUCT_PLX_9060ES,
+ 0,
+ "PLX Technology",
+ "9060ES PCI bus controller",
+ },
+ {
+ PCI_VENDOR_PROLAN, PCI_PRODUCT_PROLAN_NE2KETHER,
+ 0,
+ "ProLAN",
+ "Ethernet",
+ },
+ {
+ PCI_VENDOR_PROMISE, PCI_PRODUCT_PROMISE_DC5030,
+ 0,
+ "Promise Technology",
+ "DC5030",
+ },
+ {
+ PCI_VENDOR_PROMISE, PCI_PRODUCT_PROMISE_ULTRA33,
+ 0,
+ "Promise Technology",
+ "Ultra33/ATA Bus Master IDE Accelerator",
+ },
+ {
+ PCI_VENDOR_PROMISE, PCI_PRODUCT_PROMISE_ULTRA66,
+ 0,
+ "Promise Technology",
+ "Ultra66/ATA Bus Master IDE Accelerator",
+ },
+ {
+ PCI_VENDOR_PROMISE, PCI_PRODUCT_PROMISE_ULTRA100,
+ 0,
+ "Promise Technology",
+ "Ultra100/ATA Bus Master IDE Accelerator",
+ },
+ {
+ PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1020,
+ 0,
+ "Q Logic",
+ "ISP1020",
+ },
+ {
+ PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1022,
+ 0,
+ "Q Logic",
+ "ISP1022",
+ },
+ {
+ PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1080,
+ 0,
+ "Q Logic",
+ "ISP1080",
+ },
+ {
+ PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1240,
+ 0,
+ "Q Logic",
+ "ISP1240",
+ },
+ {
+ PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2100,
+ 0,
+ "Q Logic",
+ "ISP2100",
+ },
+ {
+ PCI_VENDOR_QUANTUMDESIGNS, PCI_PRODUCT_QUANTUMDESIGNS_8500,
+ 0,
+ "Quantum Designs",
+ "8500",
+ },
+ {
+ PCI_VENDOR_QUANTUMDESIGNS, PCI_PRODUCT_QUANTUMDESIGNS_8580,
+ 0,
+ "Quantum Designs",
+ "8580",
+ },
+ {
+ PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8029,
+ 0,
+ "Realtek Semiconductor",
+ "8029 Ethernet",
+ },
+ {
+ PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8129,
+ 0,
+ "Realtek Semiconductor",
+ "8129 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8139,
+ 0,
+ "Realtek Semiconductor",
+ "8139 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_Rx5C465,
+ 0,
+ "Ricoh",
+ "5C465 PCI-CardBus bridge",
+ },
+ {
+ PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_Rx5C466,
+ 0,
+ "Ricoh",
+ "5C466 PCI-CardBus bridge",
+ },
+ {
+ PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_Rx5C475,
+ 0,
+ "Ricoh",
+ "5C475 PCI-CardBus bridge",
+ },
+ {
+ PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RL5C476,
+ 0,
+ "Ricoh",
+ "5C476 PCI-CardBus bridge",
+ },
+ {
+ PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_Rx5C477,
+ 0,
+ "Ricoh",
+ "5C477 PCI-CardBus bridge",
+ },
+ {
+ PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_Rx5C478,
+ 0,
+ "Ricoh",
+ "5C478 PCI-CardBus bridge",
+ },
+ {
+ PCI_VENDOR_RISCOM, PCI_PRODUCT_RISCOM_N2,
+ 0,
+ "RISCom",
+ "N2",
+ },
+ {
+ PCI_VENDOR_RNS, PCI_PRODUCT_RNS_FDDI,
+ 0,
+ "RNS",
+ "2200 FDDI",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_VIRGE,
+ 0,
+ "S3",
+ "ViRGE",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_TRIO32,
+ 0,
+ "S3",
+ "Trio32",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_TRIO64,
+ 0,
+ "S3",
+ "Trio32/64",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_AURORA64P,
+ 0,
+ "S3",
+ "Aurora64V+",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_TRIO64UVP,
+ 0,
+ "S3",
+ "Trio64UV+",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_VIRGE_VX,
+ 0,
+ "S3",
+ "ViRGE/VX",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_868,
+ 0,
+ "S3",
+ "868",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_928,
+ 0,
+ "S3",
+ "86C928",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_864_0,
+ 0,
+ "S3",
+ "86C864-0",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_864_1,
+ 0,
+ "S3",
+ "86C864-1",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_864_2,
+ 0,
+ "S3",
+ "86C864-2",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_864_3,
+ 0,
+ "S3",
+ "86C864-3",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_964_0,
+ 0,
+ "S3",
+ "86C964-0",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_964_1,
+ 0,
+ "S3",
+ "86C964-1",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_964_2,
+ 0,
+ "S3",
+ "86C964-2",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_964_3,
+ 0,
+ "S3",
+ "86C964-3",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_968_0,
+ 0,
+ "S3",
+ "86C968-0",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_968_1,
+ 0,
+ "S3",
+ "86C968-1",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_968_2,
+ 0,
+ "S3",
+ "86C968-2",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_968_3,
+ 0,
+ "S3",
+ "86C968-3",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_TRIO64V2_DX,
+ 0,
+ "S3",
+ "Trio64V2/DX",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_PLATO_PX,
+ 0,
+ "S3",
+ "Plato/PX",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_TRIO3D,
+ 0,
+ "S3",
+ "86C365 Trio3D",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_VIRGE_DX,
+ 0,
+ "S3",
+ "ViRGE/DX",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_VIRGE_GX2,
+ 0,
+ "S3",
+ "ViRGE/GX2",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_TRIO3D2X,
+ 0,
+ "S3",
+ "Trio3D/2X",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_SAVAGE3D,
+ 0,
+ "S3",
+ "Savage3D",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_SAVAGE3D_MV,
+ 0,
+ "S3",
+ "Savage3D+MV",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_SAVAGE4,
+ 0,
+ "S3",
+ "Savage4",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_VIRGE_MX,
+ 0,
+ "S3",
+ "ViRGE/MX",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_VIRGE_MXP,
+ 0,
+ "S3",
+ "ViRGE/MXP",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_SAVAGE_MX_MV,
+ 0,
+ "S3",
+ "Savage/MX+MV",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_SAVAGE_MX,
+ 0,
+ "S3",
+ "Savage/MX",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_SAVAGE_IX_MV,
+ 0,
+ "S3",
+ "Savage/IX+MV",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_SAVAGE_IX,
+ 0,
+ "S3",
+ "Savage/IX",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_SAVAGE2000,
+ 0,
+ "S3",
+ "Savage2000",
+ },
+ {
+ PCI_VENDOR_S3, PCI_PRODUCT_S3_SONICVIBES,
+ 0,
+ "S3",
+ "SonicVibes",
+ },
+ {
+ PCI_VENDOR_SAMSUNGSEMI, PCI_PRODUCT_SAMSUNGSEMI_KS8920,
+ 0,
+ "Samsung Semiconductors",
+ "KS8920 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC3,
+ 0,
+ "Silicon Graphics",
+ "IOC3",
+ },
+ {
+ PCI_VENDOR_SGI, PCI_PRODUCT_SGI_RAD1,
+ 0,
+ "Silicon Graphics",
+ "PsiTech RAD1",
+ },
+ {
+ PCI_VENDOR_SGI, PCI_PRODUCT_SGI_TIGON,
+ 0,
+ "Silicon Graphics",
+ "Tigon Gigabit Ethernet",
+ },
+ {
+ PCI_VENDOR_SGSTHOMSON, PCI_PRODUCT_SGSTHOMSON_2000,
+ 0,
+ "SGS Thomson Microelectric",
+ "STG 2000X",
+ },
+ {
+ PCI_VENDOR_SGSTHOMSON, PCI_PRODUCT_SGSTHOMSON_1764,
+ 0,
+ "SGS Thomson Microelectric",
+ "STG 1764X",
+ },
+ {
+ PCI_VENDOR_SIBYTE, PCI_PRODUCT_SIBYTE_SB1250_PCI,
+ 0,
+ "SiByte, Inc.",
+ "BCM1250 PCI Host Bridge",
+ },
+ {
+ PCI_VENDOR_SIBYTE, PCI_PRODUCT_SIBYTE_SB1250_LDT,
+ 0,
+ "SiByte, Inc.",
+ "BCM1250 HyperTransport Host Bridge",
+ },
+ {
+ PCI_VENDOR_SIGMA, PCI_PRODUCT_SIGMA_HOLLYWOODPLUS,
+ 0,
+ "Sigma Designs",
+ "REALmagic Hollywood-Plus MPEG-2 Decoder",
+ },
+ {
+ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_86C201,
+ 0,
+ "Silicon Integrated System",
+ "86C201",
+ },
+ {
+ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_86C202,
+ 0,
+ "Silicon Integrated System",
+ "86C202",
+ },
+ {
+ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_86C205,
+ 0,
+ "Silicon Integrated System",
+ "86C205",
+ },
+ {
+ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_85C503,
+ 0,
+ "Silicon Integrated System",
+ "85C503 or 5597/5598 ISA bridge",
+ },
+ {
+ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_600PMC,
+ 0,
+ "Silicon Integrated System",
+ "600 Power Mngmt Controller",
+ },
+ {
+ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_5597_VGA,
+ 0,
+ "Silicon Integrated System",
+ "5597/5598 integrated VGA",
+ },
+ {
+ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_85C501,
+ 0,
+ "Silicon Integrated System",
+ "85C501",
+ },
+ {
+ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_85C496,
+ 0,
+ "Silicon Integrated System",
+ "85C496",
+ },
+ {
+ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_530HB,
+ 0,
+ "Silicon Integrated System",
+ "530 Host to PCI Bridge",
+ },
+ {
+ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_85C601,
+ 0,
+ "Silicon Integrated System",
+ "85C601",
+ },
+ {
+ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_900,
+ 0,
+ "Silicon Integrated System",
+ "SiS 900 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_5597_IDE,
+ 0,
+ "Silicon Integrated System",
+ "5597/5598 IDE controller",
+ },
+ {
+ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_5597_HB,
+ 0,
+ "Silicon Integrated System",
+ "5597/5598 host bridge",
+ },
+ {
+ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_530VGA,
+ 0,
+ "Silicon Integrated System",
+ "530 GUI Accelerator+3D",
+ },
+ {
+ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_6326,
+ 0,
+ "Silicon Integrated System",
+ "6326 AGP VGA",
+ },
+ {
+ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_5597_USB,
+ 0,
+ "Silicon Integrated System",
+ "5597/5598 USB host controller",
+ },
+ {
+ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7016,
+ 0,
+ "Silicon Integrated System",
+ "SiS 7016 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_SILMOTION, PCI_PRODUCT_SILMOTION_LYNX_E,
+ 0,
+ "Silicon Motion",
+ "Lynx E",
+ },
+ {
+ PCI_VENDOR_SMC, PCI_PRODUCT_SMC_37C665,
+ 0,
+ "Standard Microsystems",
+ "FDC 37C665",
+ },
+ {
+ PCI_VENDOR_SMC, PCI_PRODUCT_SMC_37C922,
+ 0,
+ "Standard Microsystems",
+ "FDC 37C922",
+ },
+ {
+ PCI_VENDOR_SMC, PCI_PRODUCT_SMC_83C170,
+ 0,
+ "Standard Microsystems",
+ "83C170 (\"EPIC/100\") Fast Ethernet",
+ },
+ {
+ PCI_VENDOR_SMC, PCI_PRODUCT_SMC_83C175,
+ 0,
+ "Standard Microsystems",
+ "83C175 (\"EPIC/100\") Fast Ethernet",
+ },
+ {
+ PCI_VENDOR_SOLIDUM, PCI_PRODUCT_SOLIDUM_AMD971,
+ 0,
+ "Solidum Systems Corp.",
+ "SNP8023: AMD 971",
+ },
+ {
+ PCI_VENDOR_SOLIDUM, PCI_PRODUCT_SOLIDUM_CLASS802,
+ 0,
+ "Solidum Systems Corp.",
+ "SNP8023: Classifier Engine",
+ },
+ {
+ PCI_VENDOR_SONY, PCI_PRODUCT_SONY_CXD1947A,
+ 0,
+ "Sony",
+ "CXD1947A IEEE 1394 Host Controller",
+ },
+ {
+ PCI_VENDOR_SONY, PCI_PRODUCT_SONY_CXD32222,
+ 0,
+ "Sony",
+ "CXD3222 OHCI IEEE 1394 Host Controller",
+ },
+ {
+ PCI_VENDOR_SONY, PCI_PRODUCT_SONY_MEMSTICK,
+ 0,
+ "Sony",
+ "Memory Stick I/F Controller",
+ },
+ {
+ PCI_VENDOR_SUN, PCI_PRODUCT_SUN_EBUS,
+ 0,
+ "Sun Microsystems",
+ "PCIO Ebus2",
+ },
+ {
+ PCI_VENDOR_SUN, PCI_PRODUCT_SUN_HMENETWORK,
+ 0,
+ "Sun Microsystems",
+ "PCIO Happy Meal Ethernet",
+ },
+ {
+ PCI_VENDOR_SUN, PCI_PRODUCT_SUN_SIMBA,
+ 0,
+ "Sun Microsystems",
+ "Simba PCI bridge",
+ },
+ {
+ PCI_VENDOR_SUN, PCI_PRODUCT_SUN_MS_IIep,
+ 0,
+ "Sun Microsystems",
+ "microSPARC IIep PCI",
+ },
+ {
+ PCI_VENDOR_SUN, PCI_PRODUCT_SUN_US_IIi,
+ 0,
+ "Sun Microsystems",
+ "UltraSPARC IIi PCI",
+ },
+ {
+ PCI_VENDOR_SUNDANCETI, PCI_PRODUCT_SUNDANCETI_ST201,
+ 0,
+ "Sundance Technology",
+ "ST201 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_SURECOM, PCI_PRODUCT_SURECOM_NE34,
+ 0,
+ "Surecom Technology",
+ "NE-34 Ethernet",
+ },
+ {
+ PCI_VENDOR_SYMPHONY, PCI_PRODUCT_SYMPHONY_82C101,
+ 0,
+ "Symphony Labs",
+ "82C101",
+ },
+ {
+ PCI_VENDOR_SYMPHONY, PCI_PRODUCT_SYMPHONY_82C103,
+ 0,
+ "Symphony Labs",
+ "82C103",
+ },
+ {
+ PCI_VENDOR_SYMPHONY, PCI_PRODUCT_SYMPHONY_82C105,
+ 0,
+ "Symphony Labs",
+ "82C105",
+ },
+ {
+ PCI_VENDOR_SYMPHONY2, PCI_PRODUCT_SYMPHONY2_82C101,
+ 0,
+ "Symphony Labs (2nd PCI Vendor ID)",
+ "82C101",
+ },
+ {
+ PCI_VENDOR_SYMPHONY, PCI_PRODUCT_SYMPHONY_83C553,
+ 0,
+ "Symphony Labs",
+ "83C553 PCI-ISA Bridge",
+ },
+ {
+ PCI_VENDOR_SCHNEIDERKOCH, PCI_PRODUCT_SCHNEIDERKOCH_SKNET_FDDI,
+ 0,
+ "Schneider & Koch",
+ "SK-NET FDDI-xP",
+ },
+ {
+ PCI_VENDOR_TEKRAM, PCI_PRODUCT_TEKRAM_DC290,
+ 0,
+ "Tekram Technology (1st PCI Vendor ID)",
+ "DC-290(M)",
+ },
+ {
+ PCI_VENDOR_TEKRAM2, PCI_PRODUCT_TEKRAM2_DC690C,
+ 0,
+ "Tekram Technology (2nd PCI Vendor ID)",
+ "DC-690C",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_TLAN,
+ 0,
+ "Texas Instruments",
+ "TLAN",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_TVP4020,
+ 0,
+ "Texas Instruments",
+ "TVP4020 Permedia 2",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_TSB12LV21,
+ 0,
+ "Texas Instruments",
+ "TSB12LV21 IEEE 1394 Host Controller",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_TSB12LV22,
+ 0,
+ "Texas Instruments",
+ "TSB12LV22 OHCI IEEE 1394 Host Controller",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_TSB12LV23,
+ 0,
+ "Texas Instruments",
+ "TSB12LV23 OHCI IEEE 1394 Host Controller",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_TSB12LV26,
+ 0,
+ "Texas Instruments",
+ "TSB12LV26 OHCI IEEE 1394 Host Controller",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1130,
+ 0,
+ "Texas Instruments",
+ "PCI1130 PCI-CardBus Bridge",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1031,
+ 0,
+ "Texas Instruments",
+ "PCI1031 PCI-PCMCIA Bridge",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1131,
+ 0,
+ "Texas Instruments",
+ "PCI1131 PCI-CardBus Bridge",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1250,
+ 0,
+ "Texas Instruments",
+ "PCI1250 PCI-CardBus Bridge",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1220,
+ 0,
+ "Texas Instruments",
+ "PCI1220 PCI-CardBus Bridge",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1221,
+ 0,
+ "Texas Instruments",
+ "PCI1221 PCI-CardBus Bridge",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1450,
+ 0,
+ "Texas Instruments",
+ "PCI1450 PCI-CardBus Bridge",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1225,
+ 0,
+ "Texas Instruments",
+ "PCI1225 PCI-CardBus Bridge",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1251,
+ 0,
+ "Texas Instruments",
+ "PCI1251 PCI-CardBus Bridge",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1211,
+ 0,
+ "Texas Instruments",
+ "PCI1211 PCI-CardBus Bridge",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1251B,
+ 0,
+ "Texas Instruments",
+ "PCI1251B PCI-CardBus Bridge",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI2030,
+ 0,
+ "Texas Instruments",
+ "PCI2030 PCI-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1420,
+ 0,
+ "Texas Instruments",
+ "PCI1420 PCI-CardBus Bridge",
+ },
+ {
+ PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1451,
+ 0,
+ "Texas Instruments",
+ "PCI1451 PCI-CardBus Bridge",
+ },
+ {
+ PCI_VENDOR_TOSHIBA, PCI_PRODUCT_TOSHIBA_R4X00,
+ 0,
+ "Toshiba America",
+ "R4x00 Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_TOSHIBA, PCI_PRODUCT_TOSHIBA_TC35856F,
+ 0,
+ "Toshiba America",
+ "TC35856F ATM (\"Meteor\")",
+ },
+ {
+ PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_HOST,
+ 0,
+ "Toshiba America Info Systems",
+ "Host Bridge/Controller",
+ },
+ {
+ PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ISA,
+ 0,
+ "Toshiba America Info Systems",
+ "ISA Bridge",
+ },
+ {
+ PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC95,
+ 0,
+ "Toshiba America Info Systems",
+ "ToPIC95 CardBus-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC95B,
+ 0,
+ "Toshiba America Info Systems",
+ "ToPIC95B CardBus-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC97,
+ 0,
+ "Toshiba America Info Systems",
+ "ToPIC97 CardBus-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC100,
+ 0,
+ "Toshiba America Info Systems",
+ "ToPIC100 CardBus-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_FIRO,
+ 0,
+ "Toshiba America Info Systems",
+ "Fast Infrared Type O",
+ },
+ {
+ PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_CYBERBLADE_I7,
+ 0,
+ "Trident Microsystems",
+ "CyberBlade i7",
+ },
+ {
+ PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_TGUI_9320,
+ 0,
+ "Trident Microsystems",
+ "TGUI 9320",
+ },
+ {
+ PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_TGUI_9350,
+ 0,
+ "Trident Microsystems",
+ "TGUI 9350",
+ },
+ {
+ PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_TGUI_9360,
+ 0,
+ "Trident Microsystems",
+ "TGUI 9360",
+ },
+ {
+ PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_CYBER_9397,
+ 0,
+ "Trident Microsystems",
+ "CYBER 9397",
+ },
+ {
+ PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_CYBER_9397DVD,
+ 0,
+ "Trident Microsystems",
+ "CYBER 9397DVD",
+ },
+ {
+ PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_CYBER_9525,
+ 0,
+ "Trident Microsystems",
+ "CYBER 9525",
+ },
+ {
+ PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_TGUI_9420,
+ 0,
+ "Trident Microsystems",
+ "TGUI 9420",
+ },
+ {
+ PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_TGUI_9440,
+ 0,
+ "Trident Microsystems",
+ "TGUI 9440",
+ },
+ {
+ PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_TGUI_9660,
+ 0,
+ "Trident Microsystems",
+ "TGUI 9660",
+ },
+ {
+ PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_TGUI_9680,
+ 0,
+ "Trident Microsystems",
+ "TGUI 9680",
+ },
+ {
+ PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_TGUI_9682,
+ 0,
+ "Trident Microsystems",
+ "TGUI 9682",
+ },
+ {
+ PCI_VENDOR_TRIONES, PCI_PRODUCT_TRIONES_HPT366,
+ 0,
+ "Triones Technologies",
+ "HPT366/370 IDE Controller",
+ },
+ {
+ PCI_VENDOR_TRITECH, PCI_PRODUCT_TRITECH_TR25202,
+ 0,
+ "TriTech Microelectronics",
+ "Pyramid3D TR25202",
+ },
+ {
+ PCI_VENDOR_TSENG, PCI_PRODUCT_TSENG_ET4000_W32P_A,
+ 0,
+ "Tseng Labs",
+ "ET4000w32p rev A",
+ },
+ {
+ PCI_VENDOR_TSENG, PCI_PRODUCT_TSENG_ET4000_W32P_B,
+ 0,
+ "Tseng Labs",
+ "ET4000w32p rev B",
+ },
+ {
+ PCI_VENDOR_TSENG, PCI_PRODUCT_TSENG_ET4000_W32P_C,
+ 0,
+ "Tseng Labs",
+ "ET4000w32p rev C",
+ },
+ {
+ PCI_VENDOR_TSENG, PCI_PRODUCT_TSENG_ET4000_W32P_D,
+ 0,
+ "Tseng Labs",
+ "ET4000w32p rev D",
+ },
+ {
+ PCI_VENDOR_TSENG, PCI_PRODUCT_TSENG_ET6000,
+ 0,
+ "Tseng Labs",
+ "ET6000",
+ },
+ {
+ PCI_VENDOR_UMC, PCI_PRODUCT_UMC_UM82C881,
+ 0,
+ "United Microelectronics",
+ "UM82C881 486 Chipset",
+ },
+ {
+ PCI_VENDOR_UMC, PCI_PRODUCT_UMC_UM82C886,
+ 0,
+ "United Microelectronics",
+ "UM82C886 ISA Bridge",
+ },
+ {
+ PCI_VENDOR_UMC, PCI_PRODUCT_UMC_UM8673F,
+ 0,
+ "United Microelectronics",
+ "UM8673F EIDE Controller",
+ },
+ {
+ PCI_VENDOR_UMC, PCI_PRODUCT_UMC_UM8881,
+ 0,
+ "United Microelectronics",
+ "UM8881 HB4 486 PCI Chipset",
+ },
+ {
+ PCI_VENDOR_UMC, PCI_PRODUCT_UMC_UM82C891,
+ 0,
+ "United Microelectronics",
+ "UM82C891",
+ },
+ {
+ PCI_VENDOR_UMC, PCI_PRODUCT_UMC_UM886A,
+ 0,
+ "United Microelectronics",
+ "UM886A",
+ },
+ {
+ PCI_VENDOR_UMC, PCI_PRODUCT_UMC_UM8886BF,
+ 0,
+ "United Microelectronics",
+ "UM8886BF",
+ },
+ {
+ PCI_VENDOR_UMC, PCI_PRODUCT_UMC_UM8710,
+ 0,
+ "United Microelectronics",
+ "UM8710",
+ },
+ {
+ PCI_VENDOR_UMC, PCI_PRODUCT_UMC_UM8886,
+ 0,
+ "United Microelectronics",
+ "UM8886",
+ },
+ {
+ PCI_VENDOR_UMC, PCI_PRODUCT_UMC_UM8881F,
+ 0,
+ "United Microelectronics",
+ "UM8881F PCI-Host bridge",
+ },
+ {
+ PCI_VENDOR_UMC, PCI_PRODUCT_UMC_UM8886F,
+ 0,
+ "United Microelectronics",
+ "UM8886F PCI-ISA bridge",
+ },
+ {
+ PCI_VENDOR_UMC, PCI_PRODUCT_UMC_UM8886A,
+ 0,
+ "United Microelectronics",
+ "UM8886A",
+ },
+ {
+ PCI_VENDOR_UMC, PCI_PRODUCT_UMC_UM8891A,
+ 0,
+ "United Microelectronics",
+ "UM8891A",
+ },
+ {
+ PCI_VENDOR_UMC, PCI_PRODUCT_UMC_UM9017F,
+ 0,
+ "United Microelectronics",
+ "UM9017F",
+ },
+ {
+ PCI_VENDOR_UMC, PCI_PRODUCT_UMC_UM8886N,
+ 0,
+ "United Microelectronics",
+ "UM8886N",
+ },
+ {
+ PCI_VENDOR_UMC, PCI_PRODUCT_UMC_UM8891N,
+ 0,
+ "United Microelectronics",
+ "UM8891N",
+ },
+ {
+ PCI_VENDOR_ULSI, PCI_PRODUCT_ULSI_US201,
+ 0,
+ "ULSI Systems",
+ "US201",
+ },
+ {
+ PCI_VENDOR_USR, PCI_PRODUCT_USR_3CP5609,
+ 0,
+ "US Robotics (3Com)",
+ "3CP5609 PCI 16550 Modem",
+ },
+ {
+ PCI_VENDOR_V3, PCI_PRODUCT_V3_V292PBC,
+ 0,
+ "V3 Semiconductor",
+ "V292PBC AMD290x0 Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_V3, PCI_PRODUCT_V3_V960PBC,
+ 0,
+ "V3 Semiconductor",
+ "V960PBC i960 Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_V3, PCI_PRODUCT_V3_V96DPC,
+ 0,
+ "V3 Semiconductor",
+ "V96DPC i960 (Dual) Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8371_HB,
+ 0,
+ "VIA Technologies",
+ "VT8371 (Apollo KX133) Host Bridge",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8501_MVP4,
+ 0,
+ "VIA Technologies",
+ "VT8501 MVP4 System Controller",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C505,
+ 0,
+ "VIA Technologies",
+ "VT82C505 (Pluto)",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C561,
+ 0,
+ "VIA Technologies",
+ "VT82C561",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C586A_IDE,
+ 0,
+ "VIA Technologies",
+ "VT82C586A IDE Controller",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C576,
+ 0,
+ "VIA Technologies",
+ "VT82C576 3V",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C580VP,
+ 0,
+ "VIA Technologies",
+ "VT82C580 (Apollo VP) Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C586_ISA,
+ 0,
+ "VIA Technologies",
+ "VT82C586 (Apollo VP) PCI-ISA Bridge",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C595,
+ 0,
+ "VIA Technologies",
+ "VT82C595 (Apollo VP2) Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C596A,
+ 0,
+ "VIA Technologies",
+ "VT82C596A (Apollo Pro) PCI-ISA Bridge",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C597,
+ 0,
+ "VIA Technologies",
+ "VT82C597 (Apollo VP3) Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C598PCI,
+ 0,
+ "VIA Technologies",
+ "VT82C598 (Apollo MVP3) Host-PCI",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C686A_ISA,
+ 0,
+ "VIA Technologies",
+ "VT82C686A (Apollo KX133) PCI-ISA Bridge",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C691,
+ 0,
+ "VIA Technologies",
+ "VT82C691 (Apollo Pro) Host-PCI",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C693,
+ 0,
+ "VIA Technologies",
+ "VT82C693 (Apollo Pro Plus) Host-PCI",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT86C926,
+ 0,
+ "VIA Technologies",
+ "VT86C926 Amazon PCI-Ethernet Controller",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C570M,
+ 0,
+ "VIA Technologies",
+ "VT82C570M (Apollo) Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C570MV,
+ 0,
+ "VIA Technologies",
+ "VT82C570M (Apollo) PCI-ISA Bridge",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C586_IDE,
+ 0,
+ "VIA Technologies",
+ "VT82C586 (Apollo VP) IDE Controller",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C595_2,
+ 0,
+ "VIA Technologies",
+ "VT82C595 (Apollo VP2) Host-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT83C572,
+ 0,
+ "VIA Technologies",
+ "VT83C572 USB Controller",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C586_PWR,
+ 0,
+ "VIA Technologies",
+ "VT82C586 (Apollo VP) Power Management Controller",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT3043,
+ 0,
+ "VIA Technologies",
+ "VT3043 (Rhine) 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C686A_SMB,
+ 0,
+ "VIA Technologies",
+ "VT82C686A SMBus Controller",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C686A_AC97,
+ 0,
+ "VIA Technologies",
+ "VT82C686A AC-97 Audio Controller",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C686A_MC97,
+ 0,
+ "VIA Technologies",
+ "VT82C686A MC-97 Modem Controller",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT86C100A,
+ 0,
+ "VIA Technologies",
+ "VT86C100A (Rhine-II) 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8371_PPB,
+ 0,
+ "VIA Technologies",
+ "VT8371 (Apollo KX133) PCI-PCI Bridge",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8501AGP,
+ 0,
+ "VIA Technologies",
+ "VT8501 PCI-AGP",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C597AGP,
+ 0,
+ "VIA Technologies",
+ "VT82C597 (Apollo VP3) PCI-AGP",
+ },
+ {
+ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C598AGP,
+ 0,
+ "VIA Technologies",
+ "VT82C598 (Apollo MVP3) PCI-AGP",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_60x0,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6000/6020/6050",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6000B,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6000B/6010",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x10,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6110/6510",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x20,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6120/6520",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6530,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6530",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6550,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6550",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x17,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6117/6517",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x27,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6127/6527",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6537,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6537",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6557,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6557/6557-ECC",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x15,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6115/6515",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x25,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6125/6525",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6535,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6535",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6555,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6555/6555-ECC",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x17RP,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6117RP/GDT6517RP",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x27RP,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6127RP/GDT6527RP",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6537RP,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6537RP",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6557RP,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6557RP",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x11RP,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6111RP/GDT6511RP",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x21RP,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6121RP/GDT6521RP",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x17RD,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6117RD/GDT6517RD",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x27RD,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6127RD/GDT6527RD",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6537RD,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6537RD",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6557RD,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6557RD",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x11RD,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6111RD/GDT6511RD",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x21RD,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6121RD/GDT6521RD",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x18RD,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6118RD/GDT6518RD/GDT6618RD",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x28RD,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6128RD/GDT6528RD/GDT6628RD",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x38RD,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6538RD/GDT6638RD",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x58RD,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6558RD/GDT6658RD",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_7x18RN,
+ 0,
+ "Vortex Computer Systems",
+ "GDT7118RN/GDT7518RN/GDT7618RN",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_7x28RN,
+ 0,
+ "Vortex Computer Systems",
+ "GDT7128RN/GDT7528RN/GDT7628RN",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_7x38RN,
+ 0,
+ "Vortex Computer Systems",
+ "GDT7538RN/GDT7638RN",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_7x58RN,
+ 0,
+ "Vortex Computer Systems",
+ "GDT7558RN/GDT7658RN",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x19RD,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6519RD/GDT6619RD",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x29RD,
+ 0,
+ "Vortex Computer Systems",
+ "GDT6529RD/GDT6629RD",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_7x19RN,
+ 0,
+ "Vortex Computer Systems",
+ "GDT7519RN/GDT7619RN",
+ },
+ {
+ PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_7x29RN,
+ 0,
+ "Vortex Computer Systems",
+ "GDT7529RN/GDT7629RN",
+ },
+ {
+ PCI_VENDOR_VLSI, PCI_PRODUCT_VLSI_82C592,
+ 0,
+ "VLSI Technology",
+ "82C592 CPU Bridge",
+ },
+ {
+ PCI_VENDOR_VLSI, PCI_PRODUCT_VLSI_82C593,
+ 0,
+ "VLSI Technology",
+ "82C593 ISA Bridge",
+ },
+ {
+ PCI_VENDOR_VLSI, PCI_PRODUCT_VLSI_82C594,
+ 0,
+ "VLSI Technology",
+ "82C594 Wildcat System Controller",
+ },
+ {
+ PCI_VENDOR_VLSI, PCI_PRODUCT_VLSI_82C596597,
+ 0,
+ "VLSI Technology",
+ "82C596/597 Wildcat ISA Bridge",
+ },
+ {
+ PCI_VENDOR_VLSI, PCI_PRODUCT_VLSI_82C541,
+ 0,
+ "VLSI Technology",
+ "82C541",
+ },
+ {
+ PCI_VENDOR_VLSI, PCI_PRODUCT_VLSI_82C543,
+ 0,
+ "VLSI Technology",
+ "82C543",
+ },
+ {
+ PCI_VENDOR_VLSI, PCI_PRODUCT_VLSI_82C532,
+ 0,
+ "VLSI Technology",
+ "82C532",
+ },
+ {
+ PCI_VENDOR_VLSI, PCI_PRODUCT_VLSI_82C534,
+ 0,
+ "VLSI Technology",
+ "82C534",
+ },
+ {
+ PCI_VENDOR_VLSI, PCI_PRODUCT_VLSI_82C535,
+ 0,
+ "VLSI Technology",
+ "82C535",
+ },
+ {
+ PCI_VENDOR_VLSI, PCI_PRODUCT_VLSI_82C147,
+ 0,
+ "VLSI Technology",
+ "82C147",
+ },
+ {
+ PCI_VENDOR_VLSI, PCI_PRODUCT_VLSI_82C975,
+ 0,
+ "VLSI Technology",
+ "82C975",
+ },
+ {
+ PCI_VENDOR_VLSI, PCI_PRODUCT_VLSI_82C925,
+ 0,
+ "VLSI Technology",
+ "82C925",
+ },
+ {
+ PCI_VENDOR_WEITEK, PCI_PRODUCT_WEITEK_P9000,
+ 0,
+ "Weitek",
+ "P9000",
+ },
+ {
+ PCI_VENDOR_WEITEK, PCI_PRODUCT_WEITEK_P9100,
+ 0,
+ "Weitek",
+ "P9100",
+ },
+ {
+ PCI_VENDOR_WD, PCI_PRODUCT_WD_WD33C193A,
+ 0,
+ "Western Digital",
+ "WD33C193A",
+ },
+ {
+ PCI_VENDOR_WD, PCI_PRODUCT_WD_WD33C196A,
+ 0,
+ "Western Digital",
+ "WD33C196A",
+ },
+ {
+ PCI_VENDOR_WD, PCI_PRODUCT_WD_WD33C197A,
+ 0,
+ "Western Digital",
+ "WD33C197A",
+ },
+ {
+ PCI_VENDOR_WD, PCI_PRODUCT_WD_WD7193,
+ 0,
+ "Western Digital",
+ "WD7193",
+ },
+ {
+ PCI_VENDOR_WD, PCI_PRODUCT_WD_WD7197,
+ 0,
+ "Western Digital",
+ "WD7197",
+ },
+ {
+ PCI_VENDOR_WD, PCI_PRODUCT_WD_WD33C296A,
+ 0,
+ "Western Digital",
+ "WD33C296A",
+ },
+ {
+ PCI_VENDOR_WD, PCI_PRODUCT_WD_WD34C296,
+ 0,
+ "Western Digital",
+ "WD34C296",
+ },
+ {
+ PCI_VENDOR_WD, PCI_PRODUCT_WD_90C,
+ 0,
+ "Western Digital",
+ "90C",
+ },
+ {
+ PCI_VENDOR_WINBOND, PCI_PRODUCT_WINBOND_W83769F,
+ 0,
+ "Winbond Electronics",
+ "W83769F",
+ },
+ {
+ PCI_VENDOR_WINBOND, PCI_PRODUCT_WINBOND_W89C840F,
+ 0,
+ "Winbond Electronics",
+ "W89C840F 10/100 Ethernet",
+ },
+ {
+ PCI_VENDOR_WINBOND, PCI_PRODUCT_WINBOND_W89C940F,
+ 0,
+ "Winbond Electronics",
+ "W89C940F Ethernet",
+ },
+ {
+ PCI_VENDOR_WINBOND, PCI_PRODUCT_WINBOND_W89C940F_1,
+ 0,
+ "Winbond Electronics",
+ "W89C940F Ethernet",
+ },
+ {
+ PCI_VENDOR_XIRCOM, PCI_PRODUCT_XIRCOM_X3201_3,
+ 0,
+ "Xircom",
+ "X3201-3 Fast Ethernet Controller",
+ },
+ {
+ PCI_VENDOR_XIRCOM, PCI_PRODUCT_XIRCOM_X3201_3_21143,
+ 0,
+ "Xircom",
+ "X3201-3 Fast Ethernet Controller (21143)",
+ },
+ {
+ PCI_VENDOR_YAMAHA, PCI_PRODUCT_YAMAHA_YMF724,
+ 0,
+ "Yamaha",
+ "724 Audio",
+ },
+ {
+ PCI_VENDOR_YAMAHA, PCI_PRODUCT_YAMAHA_YMF740,
+ 0,
+ "Yamaha",
+ "740 Audio",
+ },
+ {
+ PCI_VENDOR_YAMAHA, PCI_PRODUCT_YAMAHA_YMF740C,
+ 0,
+ "Yamaha",
+ "740C (DS-1) Audio",
+ },
+ {
+ PCI_VENDOR_YAMAHA, PCI_PRODUCT_YAMAHA_YMF724F,
+ 0,
+ "Yamaha",
+ "724F (DS-1) Audio",
+ },
+ {
+ PCI_VENDOR_YAMAHA, PCI_PRODUCT_YAMAHA_YMF744B,
+ 0,
+ "Yamaha",
+ "744 (DS-1S) Audio",
+ },
+ {
+ PCI_VENDOR_YAMAHA, PCI_PRODUCT_YAMAHA_YMF754,
+ 0,
+ "Yamaha",
+ "754 (DS-1E) Audio",
+ },
+ {
+ PCI_VENDOR_ZEINET, PCI_PRODUCT_ZEINET_1221,
+ 0,
+ "Zeinet",
+ "1221",
+ },
+ {
+ PCI_VENDOR_ZIATECH, PCI_PRODUCT_ZIATECH_ZT8905,
+ 0,
+ "Ziatech",
+ "PCI-ST32 Bridge",
+ },
+ {
+ PCI_VENDOR_ZORAN, PCI_PRODUCT_ZORAN_ZR36120,
+ 0,
+ "Zoran Corporation",
+ "Video Controller",
+ },
+ {
+ PCI_VENDOR_COMPAQ, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Compaq",
+ NULL,
+ },
+ {
+ PCI_VENDOR_SYMBIOS, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Symbios Logic",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ATI, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "ATI Technologies",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ULSI, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "ULSI Systems",
+ NULL,
+ },
+ {
+ PCI_VENDOR_VLSI, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "VLSI Technology",
+ NULL,
+ },
+ {
+ PCI_VENDOR_AVANCE, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Avance Logic",
+ NULL,
+ },
+ {
+ PCI_VENDOR_NS, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "National Semiconductor",
+ NULL,
+ },
+ {
+ PCI_VENDOR_TSENG, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Tseng Labs",
+ NULL,
+ },
+ {
+ PCI_VENDOR_WEITEK, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Weitek",
+ NULL,
+ },
+ {
+ PCI_VENDOR_DEC, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Digital Equipment",
+ NULL,
+ },
+ {
+ PCI_VENDOR_CIRRUS, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Cirrus Logic",
+ NULL,
+ },
+ {
+ PCI_VENDOR_IBM, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "IBM",
+ NULL,
+ },
+ {
+ PCI_VENDOR_WD, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Western Digital",
+ NULL,
+ },
+ {
+ PCI_VENDOR_AMD, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Advanced Micro Devices",
+ NULL,
+ },
+ {
+ PCI_VENDOR_TRIDENT, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Trident Microsystems",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ACER, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Acer",
+ NULL,
+ },
+ {
+ PCI_VENDOR_MATROX, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Matrox",
+ NULL,
+ },
+ {
+ PCI_VENDOR_CHIPS, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Chips and Technologies",
+ NULL,
+ },
+ {
+ PCI_VENDOR_TOSHIBA, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Toshiba America",
+ NULL,
+ },
+ {
+ PCI_VENDOR_NEC, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "NEC",
+ NULL,
+ },
+ {
+ PCI_VENDOR_FUTUREDOMAIN, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Future Domain",
+ NULL,
+ },
+ {
+ PCI_VENDOR_SIS, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Silicon Integrated System",
+ NULL,
+ },
+ {
+ PCI_VENDOR_HP, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Hewlett-Packard",
+ NULL,
+ },
+ {
+ PCI_VENDOR_PCTECH, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "PC Technology",
+ NULL,
+ },
+ {
+ PCI_VENDOR_DPT, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Distributed Processing Technology",
+ NULL,
+ },
+ {
+ PCI_VENDOR_OPTI, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Opti",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ELSA, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Elsa",
+ NULL,
+ },
+ {
+ PCI_VENDOR_SGSTHOMSON, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "SGS Thomson Microelectric",
+ NULL,
+ },
+ {
+ PCI_VENDOR_BUSLOGIC, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "BusLogic",
+ NULL,
+ },
+ {
+ PCI_VENDOR_TI, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Texas Instruments",
+ NULL,
+ },
+ {
+ PCI_VENDOR_SONY, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Sony",
+ NULL,
+ },
+ {
+ PCI_VENDOR_OAKTECH, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Oak Technology",
+ NULL,
+ },
+ {
+ PCI_VENDOR_WINBOND, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Winbond Electronics",
+ NULL,
+ },
+ {
+ PCI_VENDOR_MOT, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Motorola",
+ NULL,
+ },
+ {
+ PCI_VENDOR_PROMISE, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Promise Technology",
+ NULL,
+ },
+ {
+ PCI_VENDOR_NUMBER9, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Number 9 Computer Company",
+ NULL,
+ },
+ {
+ PCI_VENDOR_UMC, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "United Microelectronics",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ITT, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "I. T. T.",
+ NULL,
+ },
+ {
+ PCI_VENDOR_MYLEX, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Mylex",
+ NULL,
+ },
+ {
+ PCI_VENDOR_APPLE, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Apple Computer",
+ NULL,
+ },
+ {
+ PCI_VENDOR_YAMAHA, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Yamaha",
+ NULL,
+ },
+ {
+ PCI_VENDOR_NEXGEN, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "NexGen Microsystems",
+ NULL,
+ },
+ {
+ PCI_VENDOR_QLOGIC, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Q Logic",
+ NULL,
+ },
+ {
+ PCI_VENDOR_LEADTEK, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "LeadTek Research",
+ NULL,
+ },
+ {
+ PCI_VENDOR_CONTAQ, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Contaq Microsystems",
+ NULL,
+ },
+ {
+ PCI_VENDOR_BIT3, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Bit3 Computer Corp.",
+ NULL,
+ },
+ {
+ PCI_VENDOR_OLICOM, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Olicom",
+ NULL,
+ },
+ {
+ PCI_VENDOR_SUN, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Sun Microsystems",
+ NULL,
+ },
+ {
+ PCI_VENDOR_INTERGRAPH, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Intergraph",
+ NULL,
+ },
+ {
+ PCI_VENDOR_DIAMOND, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Diamond Computer Systems",
+ NULL,
+ },
+ {
+ PCI_VENDOR_CMDTECH, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "CMD Technology",
+ NULL,
+ },
+ {
+ PCI_VENDOR_QUANTUMDESIGNS, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Quantum Designs",
+ NULL,
+ },
+ {
+ PCI_VENDOR_BROOKTREE, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Brooktree",
+ NULL,
+ },
+ {
+ PCI_VENDOR_SGI, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Silicon Graphics",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ACC, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "ACC Microelectronics",
+ NULL,
+ },
+ {
+ PCI_VENDOR_SYMPHONY, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Symphony Labs",
+ NULL,
+ },
+ {
+ PCI_VENDOR_PLX, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "PLX Technology",
+ NULL,
+ },
+ {
+ PCI_VENDOR_MADGE, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Madge Networks",
+ NULL,
+ },
+ {
+ PCI_VENDOR_3COM, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "3Com",
+ NULL,
+ },
+ {
+ PCI_VENDOR_SMC, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Standard Microsystems",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ALI, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Acer Labs",
+ NULL,
+ },
+ {
+ PCI_VENDOR_SURECOM, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Surecom Technology",
+ NULL,
+ },
+ {
+ PCI_VENDOR_SAMSUNGSEMI, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Samsung Semiconductors",
+ NULL,
+ },
+ {
+ PCI_VENDOR_NEOMAGIC, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Neomagic",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ADVSYS, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Advanced System Products",
+ NULL,
+ },
+ {
+ PCI_VENDOR_MACRONIX, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Macronix",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ES, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Evans & Sutherland",
+ NULL,
+ },
+ {
+ PCI_VENDOR_NVIDIA, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Nvidia Corporation",
+ NULL,
+ },
+ {
+ PCI_VENDOR_EMULEX, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Emulex",
+ NULL,
+ },
+ {
+ PCI_VENDOR_IMS, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Integrated Micro Solutions",
+ NULL,
+ },
+ {
+ PCI_VENDOR_TEKRAM, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Tekram Technology (1st PCI Vendor ID)",
+ NULL,
+ },
+ {
+ PCI_VENDOR_NEWBRIDGE, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Newbridge Microsystems / Tundra Semiconductor",
+ NULL,
+ },
+ {
+ PCI_VENDOR_AMCIRCUITS, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Applied Micro Circuits",
+ NULL,
+ },
+ {
+ PCI_VENDOR_REALTEK, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Realtek Semiconductor",
+ NULL,
+ },
+ {
+ PCI_VENDOR_NKK, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "NKK Corporation",
+ NULL,
+ },
+ {
+ PCI_VENDOR_INITIO, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Initio",
+ NULL,
+ },
+ {
+ PCI_VENDOR_CREATIVELABS, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Creative Labs",
+ NULL,
+ },
+ {
+ PCI_VENDOR_TRIONES, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Triones Technologies",
+ NULL,
+ },
+ {
+ PCI_VENDOR_SIGMA, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Sigma Designs",
+ NULL,
+ },
+ {
+ PCI_VENDOR_VIATECH, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "VIA Technologies",
+ NULL,
+ },
+ {
+ PCI_VENDOR_COGENT, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Cogent Data Technologies",
+ NULL,
+ },
+ {
+ PCI_VENDOR_RNS, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "RNS",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ACCTON, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Accton Technology",
+ NULL,
+ },
+ {
+ PCI_VENDOR_VORTEX, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Vortex Computer Systems",
+ NULL,
+ },
+ {
+ PCI_VENDOR_EFFICIENTNETS, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Efficent Networks",
+ NULL,
+ },
+ {
+ PCI_VENDOR_IDT, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "IDT",
+ NULL,
+ },
+ {
+ PCI_VENDOR_FORE, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "FORE Systems",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ZIATECH, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Ziatech",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ALLIANCE, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Alliance Semiconductor",
+ NULL,
+ },
+ {
+ PCI_VENDOR_SCHNEIDERKOCH, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Schneider & Koch",
+ NULL,
+ },
+ {
+ PCI_VENDOR_MUTECH, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Mutech",
+ NULL,
+ },
+ {
+ PCI_VENDOR_XIRCOM, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Xircom",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ALTERA, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Altera Corporation",
+ NULL,
+ },
+ {
+ PCI_VENDOR_TOSHIBA2, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Toshiba America Info Systems",
+ NULL,
+ },
+ {
+ PCI_VENDOR_RICOH, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Ricoh",
+ NULL,
+ },
+ {
+ PCI_VENDOR_DLINK, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "D-Link Systems",
+ NULL,
+ },
+ {
+ PCI_VENDOR_COROLLARY, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Corrollary",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ACARD, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Acard",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ZEINET, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Zeinet",
+ NULL,
+ },
+ {
+ PCI_VENDOR_GALILEO, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Galileo Technology",
+ NULL,
+ },
+ {
+ PCI_VENDOR_LITEON, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Lite-On Communications",
+ NULL,
+ },
+ {
+ PCI_VENDOR_V3, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "V3 Semiconductor",
+ NULL,
+ },
+ {
+ PCI_VENDOR_LUCENT, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "AT&T Microelectronics",
+ NULL,
+ },
+ {
+ PCI_VENDOR_DOLPHIN, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Dolphin Interconnect Solutions",
+ NULL,
+ },
+ {
+ PCI_VENDOR_AURAVISION, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Auravision",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ZORAN, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Zoran Corporation",
+ NULL,
+ },
+ {
+ PCI_VENDOR_COMPEX, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Compex",
+ NULL,
+ },
+ {
+ PCI_VENDOR_PMCSIERRA, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "PMC-Sierra",
+ NULL,
+ },
+ {
+ PCI_VENDOR_CYCLADES, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Cyclades",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ESSENTIAL, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Essential Communications",
+ NULL,
+ },
+ {
+ PCI_VENDOR_O2MICRO, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "O2 Micro Inc",
+ NULL,
+ },
+ {
+ PCI_VENDOR_3DFX, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "3Dfx Interactive",
+ NULL,
+ },
+ {
+ PCI_VENDOR_CCUBE, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "C-Cube Microsystems",
+ NULL,
+ },
+ {
+ PCI_VENDOR_AVM, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "AVM",
+ NULL,
+ },
+ {
+ PCI_VENDOR_LINEARSYS, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Linear Systems",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ASIX, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "ASIX Electronics",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ESSTECH, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "ESS Technology Inc",
+ NULL,
+ },
+ {
+ PCI_VENDOR_SILMOTION, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Silicon Motion",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ENSONIQ, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Ensoniq",
+ NULL,
+ },
+ {
+ PCI_VENDOR_DAVICOM, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Davicom Semiconductor",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ESSTECH2, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "ESS Technology Inc",
+ NULL,
+ },
+ {
+ PCI_VENDOR_TRITECH, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "TriTech Microelectronics",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ALTEON, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Alteon",
+ NULL,
+ },
+ {
+ PCI_VENDOR_RISCOM, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "RISCom",
+ NULL,
+ },
+ {
+ PCI_VENDOR_USR, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "US Robotics (3Com)",
+ NULL,
+ },
+ {
+ PCI_VENDOR_NVIDIA_SGS, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Nvidia Corporation & SGS Thomson Microelectric",
+ NULL,
+ },
+ {
+ PCI_VENDOR_AUREAL, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Aureal Semiconductor",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ADMTEK, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "ADMtek",
+ NULL,
+ },
+ {
+ PCI_VENDOR_FORTEMEDIA, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Forte Media",
+ NULL,
+ },
+ {
+ PCI_VENDOR_DOMEX, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Domex",
+ NULL,
+ },
+ {
+ PCI_VENDOR_LMC, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "LAN Media Corporation",
+ NULL,
+ },
+ {
+ PCI_VENDOR_API, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "API Networks",
+ NULL,
+ },
+ {
+ PCI_VENDOR_CONEXANT, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Conexant Systems",
+ NULL,
+ },
+ {
+ PCI_VENDOR_NETGEAR, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Netgear",
+ NULL,
+ },
+ {
+ PCI_VENDOR_3WARE, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "3ware",
+ NULL,
+ },
+ {
+ PCI_VENDOR_SUNDANCETI, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Sundance Technology",
+ NULL,
+ },
+ {
+ PCI_VENDOR_CMEDIA, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "C-Media Electronics Inc",
+ NULL,
+ },
+ {
+ PCI_VENDOR_DELTA, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Delta Electronics",
+ NULL,
+ },
+ {
+ PCI_VENDOR_SOLIDUM, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Solidum Systems Corp.",
+ NULL,
+ },
+ {
+ PCI_VENDOR_SIBYTE, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "SiByte, Inc.",
+ NULL,
+ },
+ {
+ PCI_VENDOR_SYMPHONY2, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Symphony Labs (2nd PCI Vendor ID)",
+ NULL,
+ },
+ {
+ PCI_VENDOR_TEKRAM2, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Tekram Technology (2nd PCI Vendor ID)",
+ NULL,
+ },
+ {
+ PCI_VENDOR_BROADCOM, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Broadcom",
+ NULL,
+ },
+ {
+ PCI_VENDOR_3DLABS, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "3D Labs",
+ NULL,
+ },
+ {
+ PCI_VENDOR_AVANCE2, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Avance Logic (2nd PCI Vendor ID)",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ADDTRON, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Addtron Technology",
+ NULL,
+ },
+ {
+ PCI_VENDOR_NETVIN, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "NetVin",
+ NULL,
+ },
+ {
+ PCI_VENDOR_S3, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "S3",
+ NULL,
+ },
+ {
+ PCI_VENDOR_C4T, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "c't Magazin",
+ NULL,
+ },
+ {
+ PCI_VENDOR_INTEL, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Intel",
+ NULL,
+ },
+ {
+ PCI_VENDOR_PROLAN, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "ProLAN",
+ NULL,
+ },
+ {
+ PCI_VENDOR_KTI, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "KTI",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ADP, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Adaptec",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ADP2, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Adaptec (2nd PCI Vendor ID)",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ATRONICS, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Atronics",
+ NULL,
+ },
+ {
+ PCI_VENDOR_ARC, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "ARC Logic",
+ NULL,
+ },
+ {
+ PCI_VENDOR_EPIGRAM, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "Epigram",
+ NULL,
+ },
+ {
+ PCI_VENDOR_INVALID, 0,
+ PCI_KNOWNDEV_NOPROD,
+ "INVALID VENDOR ID",
+ NULL,
+ },
+ { 0, 0, 0, NULL, NULL, }
+};
diff --git a/cfe/cfe/pci/pcireg.h b/cfe/cfe/pci/pcireg.h
new file mode 100644
index 0000000..932fc7d
--- /dev/null
+++ b/cfe/cfe/pci/pcireg.h
@@ -0,0 +1,615 @@
+/*
+ * Copyright (c) 1995, 1996, 1999
+ * Christopher G. Demetriou. All rights reserved.
+ * Copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Charles M. Hannum.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#ifndef _DEV_PCI_PCIREG_H_
+#define _DEV_PCI_PCIREG_H_
+
+/*
+ * Standardized PCI configuration register definitions and macros.
+ * Derived from information found in the ``PCI Local Bus Specification,
+ * Revision 2.2, December 18, 1998.''
+ *
+ * Note: Register and field definitions assume 32-bit register accesses.
+ */
+
+#if !defined(__ASSEMBLER__)
+typedef uint16_t pci_vendor_id_t;
+typedef uint16_t pci_product_id_t;
+
+typedef uint8_t pci_class_t;
+typedef uint8_t pci_subclass_t;
+typedef uint8_t pci_interface_t;
+typedef uint8_t pci_revision_t;
+
+typedef uint8_t pci_intr_latency_t;
+typedef uint8_t pci_intr_grant_t;
+typedef uint8_t pci_intr_pin_t;
+typedef uint8_t pci_intr_line_t;
+#endif
+
+/* some PCI bus constants */
+
+#define PCI_BUSMAX 255
+#define PCI_DEVMAX 31
+#define PCI_FUNCMAX 7
+#define PCI_REGMAX 255
+
+/*
+ * Common PCI header
+ */
+
+/*
+ * Device identification register; contains a vendor ID and a device ID.
+ */
+#define PCI_ID_REG 0x00
+
+#define PCI_VENDOR_SHIFT 0
+#define PCI_VENDOR_MASK 0xffff
+#define PCI_VENDOR(id) \
+ (((id) >> PCI_VENDOR_SHIFT) & PCI_VENDOR_MASK)
+
+#define PCI_PRODUCT_SHIFT 16
+#define PCI_PRODUCT_MASK 0xffff
+#define PCI_PRODUCT(id) \
+ (((id) >> PCI_PRODUCT_SHIFT) & PCI_PRODUCT_MASK)
+
+/*
+ * Command and status register.
+ */
+#define PCI_COMMAND_STATUS_REG 0x04
+
+#define PCI_COMMAND_SHIFT 0
+#define PCI_COMMAND_MASK 0xffff
+#define PCI_COMMAND(csr) \
+ (((csr) >> PCI_COMMAND_SHIFT) & PCI_COMMAND_MASK)
+
+#define PCI_STATUS_SHIFT 16
+#define PCI_STATUS_MASK 0xffff
+#define PCI_STATUS(csr) \
+ (((csr) >> PCI_STATUS_SHIFT) & PCI_STATUS_MASK)
+
+#define PCI_COMMAND_IO_ENABLE 0x00000001
+#define PCI_COMMAND_MEM_ENABLE 0x00000002
+#define PCI_COMMAND_MASTER_ENABLE 0x00000004
+#define PCI_COMMAND_SPECIAL_ENABLE 0x00000008
+#define PCI_COMMAND_INVALIDATE_ENABLE 0x00000010
+#define PCI_COMMAND_PALETTE_ENABLE 0x00000020
+#define PCI_COMMAND_PARITY_ENABLE 0x00000040
+#define PCI_COMMAND_STEPPING_ENABLE 0x00000080
+#define PCI_COMMAND_SERR_ENABLE 0x00000100
+#define PCI_COMMAND_BACKTOBACK_ENABLE 0x00000200
+
+#define PCI_STATUS_CAPLIST_SUPPORT 0x00100000
+#define PCI_STATUS_66MHZ_SUPPORT 0x00200000
+#define PCI_STATUS_UDF_SUPPORT 0x00400000
+#define PCI_STATUS_BACKTOBACK_SUPPORT 0x00800000
+#define PCI_STATUS_PARITY_ERROR 0x01000000
+#define PCI_STATUS_DEVSEL_FAST 0x00000000
+#define PCI_STATUS_DEVSEL_MEDIUM 0x02000000
+#define PCI_STATUS_DEVSEL_SLOW 0x04000000
+#define PCI_STATUS_DEVSEL_MASK 0x06000000
+#define PCI_STATUS_DEVSEL_SHIFT 25
+#define PCI_STATUS_DEVSEL(scr) \
+ (((scr) & PCI_STATUS_DEVSEL_MASK) >> PCI_STATUS_DEVSEL_SHIFT)
+#define PCI_STATUS_TARGET_TARGET_ABORT 0x08000000
+#define PCI_STATUS_MASTER_TARGET_ABORT 0x10000000
+#define PCI_STATUS_MASTER_ABORT 0x20000000
+#define PCI_STATUS_SYSTEM_ERROR 0x40000000
+#define PCI_STATUS_PARITY_DETECT 0x80000000
+
+/*
+ * PCI Class and Revision Register; defines type and revision of device.
+ */
+#define PCI_CLASS_REG 0x08
+
+#define PCI_CLASS_SHIFT 24
+#define PCI_CLASS_MASK 0xff
+#define PCI_CLASS(cr) \
+ (((cr) >> PCI_CLASS_SHIFT) & PCI_CLASS_MASK)
+
+#define PCI_SUBCLASS_SHIFT 16
+#define PCI_SUBCLASS_MASK 0xff
+#define PCI_SUBCLASS(cr) \
+ (((cr) >> PCI_SUBCLASS_SHIFT) & PCI_SUBCLASS_MASK)
+
+#define PCI_INTERFACE_SHIFT 8
+#define PCI_INTERFACE_MASK 0xff
+#define PCI_INTERFACE(cr) \
+ (((cr) >> PCI_INTERFACE_SHIFT) & PCI_INTERFACE_MASK)
+
+#define PCI_REVISION_SHIFT 0
+#define PCI_REVISION_MASK 0xff
+#define PCI_REVISION(cr) \
+ (((cr) >> PCI_REVISION_SHIFT) & PCI_REVISION_MASK)
+
+#define PCI_CLASS_CODE(class, subclass, interface) \
+ ((((class) & PCI_CLASS_MASK) << PCI_CLASS_SHIFT) | \
+ (((subclass) & PCI_SUBCLASS_MASK) << PCI_SUBCLASS_SHIFT) | \
+ (((interface) & PCI_INTERFACE_MASK) << PCI_INTERFACE_SHIFT))
+
+/* base classes */
+#define PCI_CLASS_PREHISTORIC 0x00
+#define PCI_CLASS_MASS_STORAGE 0x01
+#define PCI_CLASS_NETWORK 0x02
+#define PCI_CLASS_DISPLAY 0x03
+#define PCI_CLASS_MULTIMEDIA 0x04
+#define PCI_CLASS_MEMORY 0x05
+#define PCI_CLASS_BRIDGE 0x06
+#define PCI_CLASS_COMMUNICATIONS 0x07
+#define PCI_CLASS_SYSTEM 0x08
+#define PCI_CLASS_INPUT 0x09
+#define PCI_CLASS_DOCK 0x0a
+#define PCI_CLASS_PROCESSOR 0x0b
+#define PCI_CLASS_SERIALBUS 0x0c
+#define PCI_CLASS_WIRELESS 0x0d
+#define PCI_CLASS_I2O 0x0e
+#define PCI_CLASS_SATCOM 0x0f
+#define PCI_CLASS_CRYPTO 0x10
+#define PCI_CLASS_DASP 0x11
+#define PCI_CLASS_UNDEFINED 0xff
+
+/* 0x00 prehistoric subclasses */
+#define PCI_SUBCLASS_PREHISTORIC_MISC 0x00
+#define PCI_SUBCLASS_PREHISTORIC_VGA 0x01
+
+/* 0x01 mass storage subclasses */
+#define PCI_SUBCLASS_MASS_STORAGE_SCSI 0x00
+#define PCI_SUBCLASS_MASS_STORAGE_IDE 0x01
+#define PCI_SUBCLASS_MASS_STORAGE_FLOPPY 0x02
+#define PCI_SUBCLASS_MASS_STORAGE_IPI 0x03
+#define PCI_SUBCLASS_MASS_STORAGE_RAID 0x04
+#define PCI_SUBCLASS_MASS_STORAGE_MISC 0x80
+
+/* 0x02 network subclasses */
+#define PCI_SUBCLASS_NETWORK_ETHERNET 0x00
+#define PCI_SUBCLASS_NETWORK_TOKENRING 0x01
+#define PCI_SUBCLASS_NETWORK_FDDI 0x02
+#define PCI_SUBCLASS_NETWORK_ATM 0x03
+#define PCI_SUBCLASS_NETWORK_ISDN 0x04
+#define PCI_SUBCLASS_NETWORK_WORLDFIP 0x05
+#define PCI_SUBCLASS_NETWORK_PCIMGMULTICOMP 0x06
+#define PCI_SUBCLASS_NETWORK_MISC 0x80
+
+/* 0x03 display subclasses */
+#define PCI_SUBCLASS_DISPLAY_VGA 0x00
+#define PCI_SUBCLASS_DISPLAY_XGA 0x01
+#define PCI_SUBCLASS_DISPLAY_3D 0x02
+#define PCI_SUBCLASS_DISPLAY_MISC 0x80
+
+/* 0x04 multimedia subclasses */
+#define PCI_SUBCLASS_MULTIMEDIA_VIDEO 0x00
+#define PCI_SUBCLASS_MULTIMEDIA_AUDIO 0x01
+#define PCI_SUBCLASS_MULTIMEDIA_TELEPHONY 0x02
+#define PCI_SUBCLASS_MULTIMEDIA_MISC 0x80
+
+/* 0x05 memory subclasses */
+#define PCI_SUBCLASS_MEMORY_RAM 0x00
+#define PCI_SUBCLASS_MEMORY_FLASH 0x01
+#define PCI_SUBCLASS_MEMORY_MISC 0x80
+
+/* 0x06 bridge subclasses */
+#define PCI_SUBCLASS_BRIDGE_HOST 0x00
+#define PCI_SUBCLASS_BRIDGE_ISA 0x01
+#define PCI_SUBCLASS_BRIDGE_EISA 0x02
+#define PCI_SUBCLASS_BRIDGE_MCA 0x03
+#define PCI_SUBCLASS_BRIDGE_PCI 0x04
+#define PCI_SUBCLASS_BRIDGE_PCMCIA 0x05
+#define PCI_SUBCLASS_BRIDGE_NUBUS 0x06
+#define PCI_SUBCLASS_BRIDGE_CARDBUS 0x07
+#define PCI_SUBCLASS_BRIDGE_RACEWAY 0x08
+#define PCI_SUBCLASS_BRIDGE_STPCI 0x09
+#define PCI_SUBCLASS_BRIDGE_INFINIBAND 0x0a
+#define PCI_SUBCLASS_BRIDGE_MISC 0x80
+
+/* 0x07 communications subclasses */
+#define PCI_SUBCLASS_COMMUNICATIONS_SERIAL 0x00
+#define PCI_SUBCLASS_COMMUNICATIONS_PARALLEL 0x01
+#define PCI_SUBCLASS_COMMUNICATIONS_MPSERIAL 0x02
+#define PCI_SUBCLASS_COMMUNICATIONS_MODEM 0x03
+#define PCI_SUBCLASS_COMMUNICATIONS_MISC 0x80
+
+/* 0x08 system subclasses */
+#define PCI_SUBCLASS_SYSTEM_PIC 0x00
+#define PCI_SUBCLASS_SYSTEM_DMA 0x01
+#define PCI_SUBCLASS_SYSTEM_TIMER 0x02
+#define PCI_SUBCLASS_SYSTEM_RTC 0x03
+#define PCI_SUBCLASS_SYSTEM_PCIHOTPLUG 0x04
+#define PCI_SUBCLASS_SYSTEM_MISC 0x80
+
+/* 0x09 input subclasses */
+#define PCI_SUBCLASS_INPUT_KEYBOARD 0x00
+#define PCI_SUBCLASS_INPUT_DIGITIZER 0x01
+#define PCI_SUBCLASS_INPUT_MOUSE 0x02
+#define PCI_SUBCLASS_INPUT_SCANNER 0x03
+#define PCI_SUBCLASS_INPUT_GAMEPORT 0x04
+#define PCI_SUBCLASS_INPUT_MISC 0x80
+
+/* 0x0a dock subclasses */
+#define PCI_SUBCLASS_DOCK_GENERIC 0x00
+#define PCI_SUBCLASS_DOCK_MISC 0x80
+
+/* 0x0b processor subclasses */
+#define PCI_SUBCLASS_PROCESSOR_386 0x00
+#define PCI_SUBCLASS_PROCESSOR_486 0x01
+#define PCI_SUBCLASS_PROCESSOR_PENTIUM 0x02
+#define PCI_SUBCLASS_PROCESSOR_ALPHA 0x10
+#define PCI_SUBCLASS_PROCESSOR_POWERPC 0x20
+#define PCI_SUBCLASS_PROCESSOR_MIPS 0x30
+#define PCI_SUBCLASS_PROCESSOR_COPROC 0x40
+
+/* 0x0c serial bus subclasses */
+#define PCI_SUBCLASS_SERIALBUS_FIREWIRE 0x00
+#define PCI_SUBCLASS_SERIALBUS_ACCESS 0x01
+#define PCI_SUBCLASS_SERIALBUS_SSA 0x02
+#define PCI_SUBCLASS_SERIALBUS_USB 0x03
+#define PCI_SUBCLASS_SERIALBUS_FIBER 0x04 /* XXX _FIBRECHANNEL */
+#define PCI_SUBCLASS_SERIALBUS_SMBUS 0x05
+#define PCI_SUBCLASS_SERIALBUS_INFINIBAND 0x06
+#define PCI_SUBCLASS_SERIALBUS_IPMI 0x07
+#define PCI_SUBCLASS_SERIALBUS_SERCOS 0x08
+#define PCI_SUBCLASS_SERIALBUS_CANBUS 0x09
+
+/* 0x0d wireless subclasses */
+#define PCI_SUBCLASS_WIRELESS_IRDA 0x00
+#define PCI_SUBCLASS_WIRELESS_CONSUMERIR 0x01
+#define PCI_SUBCLASS_WIRELESS_RF 0x10
+#define PCI_SUBCLASS_WIRELESS_MISC 0x80
+
+/* 0x0e I2O (Intelligent I/O) subclasses */
+#define PCI_SUBCLASS_I2O_STANDARD 0x00
+
+/* 0x0f satellite communication subclasses */
+/* PCI_SUBCLASS_SATCOM_??? 0x00 / * XXX ??? */
+#define PCI_SUBCLASS_SATCOM_TV 0x01
+#define PCI_SUBCLASS_SATCOM_AUDIO 0x02
+#define PCI_SUBCLASS_SATCOM_VOICE 0x03
+#define PCI_SUBCLASS_SATCOM_DATA 0x04
+
+/* 0x10 encryption/decryption subclasses */
+#define PCI_SUBCLASS_CRYPTO_NETCOMP 0x00
+#define PCI_SUBCLASS_CRYPTO_ENTERTAINMENT 0x10
+#define PCI_SUBCLASS_CRYPTO_MISC 0x80
+
+/* 0x11 data acquisition and signal processing subclasses */
+#define PCI_SUBCLASS_DASP_DPIO 0x00
+#define PCI_SUBCLASS_DASP_TIMERFREQ 0x01
+#define PCI_SUBCLASS_DASP_MISC 0x80
+
+/*
+ * PCI BIST/Header Type/Latency Timer/Cache Line Size Register.
+ */
+#define PCI_BHLC_REG 0x0c
+
+#define PCI_BIST_SHIFT 24
+#define PCI_BIST_MASK 0xff
+#define PCI_BIST(bhlcr) \
+ (((bhlcr) >> PCI_BIST_SHIFT) & PCI_BIST_MASK)
+
+#define PCI_HDRTYPE_SHIFT 16
+#define PCI_HDRTYPE_MASK 0xff
+#define PCI_HDRTYPE(bhlcr) \
+ (((bhlcr) >> PCI_HDRTYPE_SHIFT) & PCI_HDRTYPE_MASK)
+
+#define PCI_HDRTYPE_TYPE(bhlcr) \
+ (PCI_HDRTYPE(bhlcr) & 0x7f)
+#define PCI_HDRTYPE_MULTIFN(bhlcr) \
+ ((PCI_HDRTYPE(bhlcr) & 0x80) != 0)
+
+#define PCI_LATTIMER_SHIFT 8
+#define PCI_LATTIMER_MASK 0xff
+#define PCI_LATTIMER(bhlcr) \
+ (((bhlcr) >> PCI_LATTIMER_SHIFT) & PCI_LATTIMER_MASK)
+#define PCI_LATTIMER_SET(bhlcr,v) \
+ (bhlcr) = ((bhlcr) & ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT)) | \
+ ((v) << PCI_LATTIMER_SHIFT)
+
+#define PCI_CACHELINE_SHIFT 0
+#define PCI_CACHELINE_MASK 0xff
+#define PCI_CACHELINE(bhlcr) \
+ (((bhlcr) >> PCI_CACHELINE_SHIFT) & PCI_CACHELINE_MASK)
+#define PCI_CACHELINE_SET(bhlcr,v) \
+ (bhlcr) = ((bhlcr) & ~(PCI_CACHELINE_MASK << PCI_CACHELINE_SHIFT)) | \
+ ((v) << PCI_CACHELINE_SHIFT)
+
+/*
+ * The currently defined header types are
+ * 00h prefix PCI_ below
+ * 01h prefix PPB_ below (PCI-to-PCI bridges)
+ * 02h prefix PCB_ below (Cardbus bridges)
+ */
+
+/*
+ * Type 00h Configuration Space extensions.
+ */
+
+/*
+ * Mapping registers
+ */
+#define PCI_MAPREG_START 0x10
+#define PCI_MAPREG_END 0x28
+
+#define PCI_MAPREG_PPB_END 0x18
+#define PCI_MAPREG_PPB_ROM 0x38
+#define PCI_MAPREG_PCB_END 0x14
+#define PCI_MAPREG_NONE 0x00
+
+#define PCI_MAPREG_TYPE(mr) \
+ ((mr) & PCI_MAPREG_TYPE_MASK)
+#define PCI_MAPREG_TYPE_MASK 0x00000001
+
+#define PCI_MAPREG_TYPE_MEM 0x00000000
+#define PCI_MAPREG_TYPE_IO 0x00000001
+
+#define PCI_MAPREG_MEM_TYPE(mr) \
+ ((mr) & PCI_MAPREG_MEM_TYPE_MASK)
+#define PCI_MAPREG_MEM_TYPE_MASK 0x00000006
+
+#define PCI_MAPREG_MEM_TYPE_32BIT 0x00000000
+#define PCI_MAPREG_MEM_TYPE_32BIT_1M 0x00000002
+#define PCI_MAPREG_MEM_TYPE_64BIT 0x00000004
+
+#define PCI_MAPREG_MEM_PREFETCHABLE(mr) \
+ (((mr) & PCI_MAPREG_MEM_PREFETCHABLE_MASK) != 0)
+#define PCI_MAPREG_MEM_PREFETCHABLE_MASK 0x00000008
+
+#define PCI_MAPREG_MEM_ADDR(mr) \
+ ((mr) & PCI_MAPREG_MEM_ADDR_MASK)
+#define PCI_MAPREG_MEM_SIZE(mr) \
+ (PCI_MAPREG_MEM_ADDR(mr) & -PCI_MAPREG_MEM_ADDR(mr))
+#define PCI_MAPREG_MEM_ADDR_MASK 0xfffffff0
+
+#define PCI_MAPREG_MEM64_ADDR(mr) \
+ ((mr) & PCI_MAPREG_MEM64_ADDR_MASK)
+#define PCI_MAPREG_MEM64_SIZE(mr) \
+ (PCI_MAPREG_MEM64_ADDR(mr) & -PCI_MAPREG_MEM64_ADDR(mr))
+#define PCI_MAPREG_MEM64_ADDR_MASK 0xfffffffffffffff0ULL
+
+#define PCI_MAPREG_IO_ADDR(mr) \
+ ((mr) & PCI_MAPREG_IO_ADDR_MASK)
+#define PCI_MAPREG_IO_SIZE(mr) \
+ (PCI_MAPREG_IO_ADDR(mr) & -PCI_MAPREG_IO_ADDR(mr))
+#define PCI_MAPREG_IO_ADDR_MASK 0xfffffffc
+
+#define PCI_MAPREG_SIZE_TO_MASK(size) \
+ (-(size))
+
+#define PCI_MAPREG(num) (PCI_MAPREG_START + 4*(num))
+#define PCI_MAPREG_NUM(offset) \
+ (((unsigned)(offset)-PCI_MAPREG_START)/4)
+
+/*
+ * Cardbus CIS pointer (PCI rev. 2.1)
+ */
+#define PCI_CARDBUS_CIS_REG 0x28
+
+/*
+ * Subsystem identification register; contains a vendor ID and a device ID.
+ * Types/macros for PCI_ID_REG apply.
+ * (PCI rev. 2.1)
+ */
+#define PCI_SUBSYS_ID_REG 0x2c
+
+/*
+ * Expansion ROM base address register; contains an address and enable bit.
+ */
+#define PCI_MAPREG_ROM 0x30
+#define PCI_MAPREG_ROM_ADDR(mr) \
+ ((mr) & PCI_MAPREG_ROM_ADDR_MASK)
+#define PCI_MAPREG_ROM_ADDR_MASK 0xfffff800
+#define PCI_MAPREG_ROM_ENABLE 0x00000001
+
+/*
+ * capabilities link list (PCI rev. 2.2)
+ */
+#define PCI_CAPLISTPTR_REG 0x34 /* header type 0 */
+#define PCI_CARDBUS_CAPLISTPTR_REG 0x14 /* header type 2 */
+#define PCI_CAPLIST_PTR(cpr) ((cpr) & 0xff)
+#define PCI_CAPLIST_NEXT(cr) (((cr) >> 8) & 0xff)
+#define PCI_CAPLIST_CAP(cr) ((cr) & 0xff)
+
+#define PCI_CAP_RESERVED0 0x00
+#define PCI_CAP_PWRMGMT 0x01
+#define PCI_CAP_AGP 0x02
+#define PCI_CAP_VPD 0x03
+#define PCI_CAP_SLOTID 0x04
+#define PCI_CAP_MBI 0x05
+#define PCI_CAP_CPCI_HOTSWAP 0x06
+#define PCI_CAP_PCIX 0x07
+#define PCI_CAP_LDT 0x08
+#define PCI_CAP_VENDSPEC 0x09
+#define PCI_CAP_DEBUGPORT 0x0a
+#define PCI_CAP_CPCI_RSRCCTL 0x0b
+#define PCI_CAP_HOTPLUG 0x0c
+
+/*
+ * Power Management Control Status Register; access via capability pointer.
+ */
+#define PCI_PMCSR_STATE_MASK 0x03
+#define PCI_PMCSR_STATE_D0 0x00
+#define PCI_PMCSR_STATE_D1 0x01
+#define PCI_PMCSR_STATE_D2 0x02
+#define PCI_PMCSR_STATE_D3 0x03
+
+/*
+ * Bus Parameter and Interrupt Configuration Register;
+ * contains interrupt pin and line.
+ */
+#define PCI_BPARAM_INTERRUPT_REG 0x3c
+
+#define PCI_BPARAM_LATENCY_SHIFT 24
+#define PCI_BPARAM_LATENCY_MASK 0xff
+#define PCI_BPARAM_LATENCY(bpir) \
+ (((bpir) >> PCI_BPARAM_LATENCY_SHIFT) & PCI_BPARAM_LATENCY_MASK)
+
+#define PCI_BPARAM_GRANT_SHIFT 16
+#define PCI_BPARAM_GRANT_MASK 0xff
+#define PCI_BPARAM_GRANT(bpir) \
+ (((bpir) >> PCI_BPARAM_GRANT_SHIFT) & PCI_BPARAM_GRANT_MASK)
+
+#define PCI_INTERRUPT_PIN_SHIFT 8
+#define PCI_INTERRUPT_PIN_MASK 0xff
+#define PCI_INTERRUPT_PIN(bpir) \
+ (((bpir) >> PCI_INTERRUPT_PIN_SHIFT) & PCI_INTERRUPT_PIN_MASK)
+
+#define PCI_INTERRUPT_LINE_SHIFT 0
+#define PCI_INTERRUPT_LINE_MASK 0xff
+#define PCI_INTERRUPT_LINE(bpir) \
+ (((bpir) >> PCI_INTERRUPT_LINE_SHIFT) & PCI_INTERRUPT_LINE_MASK)
+
+#define PCI_INTERRUPT_PIN_NONE 0x00
+#define PCI_INTERRUPT_PIN_A 0x01
+#define PCI_INTERRUPT_PIN_B 0x02
+#define PCI_INTERRUPT_PIN_C 0x03
+#define PCI_INTERRUPT_PIN_D 0x04
+#define PCI_INTERRUPT_PIN_MAX 0x04
+
+
+/*
+ * Type 01h Configuration Space extension:
+ * PCI to PCI Bridge registers (cf ppbreg.h)
+ * Derived from information found in the ``PCI to PCI Bridge
+ * Architecture Specification, Revision 1.1, December 18, 1998.''
+ */
+
+#define PPB_MAPREG_START 0x10
+#define PPB_MAPREG_END 0x18
+
+/*
+ * Bus Information Register; contains bus hierarchy and secondary latency.
+ */
+#define PPB_BUSINFO_REG 0x18
+
+#define PPB_BUSINFO_LATENCY_SHIFT 24
+#define PPB_BUSINFO_LATENCY_MASK 0xff
+#define PPB_BUSINFO_LATENCY(br) \
+ (((br) >> PPB_BUSINFO_LATENCY_SHIFT) & PPB_BUSINFO_LATENCY_MASK)
+
+#define PPB_BUSINFO_SUBORD_SHIFT 16
+#define PPB_BUSINFO_SUBORD_MASK 0xff
+#define PPB_BUSINFO_SUBORD(br) \
+ (((br) >> PPB_BUSINFO_SUBORD_SHIFT) & PPB_BUSINFO_SUBORD_MASK)
+
+#define PPB_BUSINFO_SECONDARY_SHIFT 8
+#define PPB_BUSINFO_SECONDARY_MASK 0xff
+#define PPB_BUSINFO_SECONDARY(br) \
+ (((br) >> PPB_BUSINFO_SECONDARY_SHIFT) & PPB_BUSINFO_SECONDARY_MASK)
+
+#define PPB_BUSINFO_PRIMARY_SHIFT 0
+#define PPB_BUSINFO_PRIMARY_MASK 0xff
+#define PPB_BUSINFO_PRIMARY(br) \
+ (((br) >> PPB_BUSINFO_PRIMARY_SHIFT) & PPB_BUSINFO_PRIMARY_MASK)
+
+/*
+ * IO Status Register; contains I/O base + limit and secondary status.
+ * Masks/macros for PCI_STATUS apply to Secondary Status.
+ */
+#define PPB_IO_STATUS_REG 0x1C
+
+#define PPB_IO_BASE_MASK 0x000000ff
+#define PPB_IO_LIMIT_MASK 0x0000ff00
+#define PPB_IO_ADDR_CAP_MASK 0x00000f0f
+#define PPB_IO_ADDR_CAP_16 0x00000000
+#define PPB_IO_ADDR_CAP_32 0x00000101
+#define PPB_IO_BASE(iosr) \
+ (((iosr) >> 0) & 0xff)
+#define PPB_IO_LIMIT(iosr) \
+ (((iosr) >> 8) & 0xff)
+
+#define PPB_SECSTATUS_SHIFT 16
+#define PPB_SECSTATUS_MASK 0xffff
+#define PPB_SECSTATUS(iosr) \
+ (((iosr) >> PPB_SECSTATUS_SHIFT) & PPB_SECSTATUS_MASK)
+
+/*
+ * Base and limit values for address ranges have common packing.
+ */
+#define PPB_BASE_SHIFT 0
+#define PPB_BASE_MASK 0xffff
+#define PPB_BASE(blr) \
+ (((blr) >> PPB_BASE_SHIFT) & PPB_BASE_MASK)
+
+#define PPB_LIMIT_SHIFT 16
+#define PPB_LIMIT_MASK 0xffff
+#define PPB_LIMIT(blr) \
+ (((blr) >> PPB_LIMIT_SHIFT) & PPB_LIMIT_MASK)
+
+/*
+ * Memory Registers; contains memory base + limit.
+ */
+#define PPB_MEM_REG 0x20
+#define PPB_PREFMEM_REG 0x24
+
+#define PPB_MEM_BASE_MASK 0x0000ffff
+#define PPB_MEM_LIMIT_MASK 0xffff0000
+
+/*
+ * Prefetchable Memory Upper Registers; contain high bits
+ */
+#define PPB_PREFMEM_BASE_UPPER_REG 0x28
+#define PPB_PREFMEM_LIMIT_UPPER_REG 0x2c
+
+/*
+ * IO Upper Register; contains I/O base + limit high bits
+ */
+#define PPB_IO_UPPER_REG 0x30
+
+#define PPB_IO_UPPER_BASE_MASK 0x0000ffff
+#define PPB_IO_UPPER_LIMIT_MASK 0xffff0000
+
+/*
+ * Expansion ROM Base Address Register.
+ */
+#define PPB_MAPREG_ROM 0x38
+
+/*
+ * Bridge Control and Interrupt Register
+ * Masks/macros for PCI_INTERRUPT apply to Interrupt
+ */
+#define PPB_BRCTL_INTERRUPT_REG 0x3C
+
+#define PPB_BRCTL_SHIFT 16
+#define PPB_BRCTL_MASK 0xffff
+#define PPB_BRCTL(bcir) \
+ (((bcir) >> PPB_BRCTL_SHIFT) & PPB_BRCTL_MASK)
+
+#define PPB_BRCTL_PARITY_ENABLE 0x00010000
+#define PPB_BRCTL_SERR_ENABLE 0x00020000
+#define PPB_BRCTL_ISA_ENABLE 0x00040000
+#define PPB_BRCTL_VGA_ENABLE 0x00080000
+#define PPB_BRCTL_MASTER_ABORT_MODE 0x00200000
+#define PPB_BRCTL_SECONDARY_RESET 0x00400000
+#define PPB_BRCTL_BACKTOBACK_ENABLE 0x00800000
+#define PPB_BRCTL_PRIMARY_DISCARD_TIMER 0x01000000
+#define PPB_BRCTL_SECONDARY_DISCARD_TIMER 0x02000000
+#define PPB_BRCTL_DISCARD_TIMER_STATUS 0x04000000
+#define PPB_BRCTL_DISCARD_SERR_ENABLE 0x08000000
+
+#endif /* _DEV_PCI_PCIREG_H_ */
diff --git a/cfe/cfe/pci/pcivar.h b/cfe/cfe/pci/pcivar.h
new file mode 100644
index 0000000..51f0b40
--- /dev/null
+++ b/cfe/cfe/pci/pcivar.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 1994 Charles Hannum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Charles Hannum.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#ifndef _PCIVAR_H_
+#define _PCIVAR_H_
+
+/*
+ * Definitions for PCI autoconfiguration.
+ *
+ * The initial segment of this file describes types and functions
+ * that are exported for PCI configuration and address mapping. */
+
+#include "pci_machdep.h"
+
+/* From <cpu>_pci_machdep.c */
+
+pcitag_t pci_make_tag(int, int, int);
+pcireg_t pci_conf_read(pcitag_t, int);
+void pci_conf_write(pcitag_t, int, pcireg_t);
+
+typedef enum {
+ PCI_MATCH_BYTES = 0,
+ PCI_MATCH_BITS = 1
+} pci_endian_t;
+
+int pci_map_io(pcitag_t, int, pci_endian_t, phys_addr_t *);
+int pci_map_mem(pcitag_t, int, pci_endian_t, phys_addr_t *);
+
+uint8_t inb(unsigned int port);
+uint16_t inw(unsigned int port);
+uint32_t inl(unsigned int port);
+void outb(unsigned int port, uint8_t val);
+void outw(unsigned int port, uint16_t val);
+void outl(unsigned int port, uint32_t val);
+
+int pci_map_window(phys_addr_t pa,
+ unsigned int offset, unsigned int len,
+ int l2ca, int endian);
+int pci_unmap_window(unsigned int offset, unsigned int len);
+
+/* From pciconf.c */
+
+/* Flags controlling PCI/LDT configuration options */
+
+typedef unsigned int pci_flags_t;
+
+#define PCI_FLG_NORMAL 0x00000001
+#define PCI_FLG_VERBOSE 0x00000003
+#define PCI_FLG_LDT_PREFETCH 0x00000004
+#define PCI_FLG_LDT_REV_017 0x00000008
+
+void pci_configure(pci_flags_t flags);
+void pci_show_configuration(void);
+int pci_foreachdev(int (*fn)(pcitag_t tag));
+int pci_cacheline_log2 (void);
+int pci_maxburst_log2 (void);
+
+int pci_find_device(uint32_t vid, uint32_t did, int enumidx, pcitag_t *tag);
+int pci_find_class(uint32_t class, int enumidx, pcitag_t *tag);
+
+/* From pci_subr.c */
+
+void pci_devinfo(pcireg_t, pcireg_t, int, char *);
+void pci_conf_print(pcitag_t tag);
+
+void pci_tagprintf (pcitag_t tag, const char *fmt, ...)
+#ifdef __long64
+ __attribute__((__format__(__printf__,2,3)))
+#endif
+ ;
+
+
+/*
+ * Definitions for PCI autoconfiguration.
+ *
+ * The remainder of this file describes types and functions
+ * that are used only for communication among the PCI modules
+ * implementing autoconfiguration.
+ * XXX This should be split into a separate file. */
+
+/* Build options. Debug levels >1 are for helping to bring up new
+ LDT hardware and will be annoyingly verbose otherwise. */
+
+/* PCI_DEBUG enables general checking and tracing. */
+#ifndef PCI_DEBUG
+#define PCI_DEBUG 0
+#endif
+
+/* LDT_DEBUG enables progress/error reports for LDT fabric initialization. */
+#ifndef LDT_DEBUG
+#define LDT_DEBUG 0
+#endif
+
+
+struct pci_attach_args {
+ pcitag_t pa_tag;
+ pcireg_t pa_id;
+ pcireg_t pa_class;
+};
+
+struct pci_match {
+ pcireg_t class, classmask;
+ pcireg_t id, idmask;
+};
+
+/* From <cpu>_pci_machdep.c */
+
+int pci_hwinit(pci_flags_t flags);
+void pci_hwreinit(pci_flags_t flags);
+int pci_device_preset (pcitag_t tag);
+void pci_device_setup(pcitag_t tag);
+void pci_bridge_setup(pcitag_t tag, pci_flags_t flags);
+void pci_flush(void);
+
+void pci_break_tag(pcitag_t, int *, int *, int *);
+
+int pci_canscan(pcitag_t);
+int pci_probe_tag(pcitag_t tag);
+
+pcireg_t pci_conf_read8(pcitag_t, int);
+void pci_conf_write8(pcitag_t, int, pcireg_t);
+pcireg_t pci_conf_read16(pcitag_t, int);
+void pci_conf_write16(pcitag_t, int, pcireg_t);
+pcireg_t pci_conf_read(pcitag_t, int);
+void pci_conf_write(pcitag_t, int, pcireg_t);
+#define pci_conf_read32 pci_conf_read
+#define pci_conf_write32 pci_conf_write
+int pci_conf_write_acked(pcitag_t, int, pcireg_t);
+
+uint8_t pci_int_line(uint8_t);
+
+
+/* From <board>_pci.c */
+
+uint8_t pci_int_shift_0(pcitag_t);
+uint8_t pci_int_map_0(pcitag_t);
+
+
+/* From ldtinit.c */
+
+#define LDT_PRIMARY 0
+#define LDT_SECONDARY 1
+unsigned pci_find_ldt_cap (pcitag_t tag, int secondary);
+
+void ldt_link_reset (pcitag_t tag, int delay);
+int ldt_chain_init (pcitag_t tag, int bus, pci_flags_t flags);
+
+
+/* From pci_subr.c */
+
+void pci_bdfprintf(int bus, int device, int function, const char *fmt, ...)
+#ifdef __long64
+ __attribute__((__format__(__printf__,4,5)))
+#endif
+ ;
+
+
+/* PCI bus parameters */
+struct pci_bus {
+ unsigned char min_gnt; /* largest min grant */
+ unsigned char max_lat; /* smallest max latency */
+ unsigned char devsel; /* slowest devsel */
+ char fast_b2b; /* support fast b2b */
+ char prefetch; /* support prefetch */
+ char freq66; /* support 66MHz */
+ char width64; /* 64 bit bus */
+ int bandwidth; /* # of .25us ticks/sec @ 33MHz */
+ unsigned char ndev; /* # devices (functions) on bus */
+ unsigned char def_ltim; /* default ltim counter */
+ unsigned char max_ltim; /* maximum ltim counter */
+ uint8_t primary; /* primary bus number */
+ pcitag_t tag; /* tag for this bus */
+ uint32_t min_io_addr; /* min I/O address allocated to bus */
+ uint32_t max_io_addr; /* max I/O address allocated to bus */
+ uint32_t min_mem_addr; /* min mem address allocated to bus */
+ uint32_t max_mem_addr; /* max mem address allocated to bus */
+ uint8_t inta_shift; /* base rotation of interrupt pins */
+ char no_probe; /* skip businit and query probes */
+};
+
+extern pcireg_t minpcimemaddr;
+extern pcireg_t maxpcimemaddr;
+extern pcireg_t minpciioaddr;
+extern pcireg_t maxpciioaddr;
+
+extern struct pci_bus _pci_bus[];
+extern int _pci_nbus;
+extern const int _pci_maxbus;
+
+#endif /* _PCIVAR_H_ */
diff --git a/cfe/cfe/ui/ui_cmddisp.c b/cfe/cfe/ui/ui_cmddisp.c
new file mode 100644
index 0000000..8609f1c
--- /dev/null
+++ b/cfe/cfe/ui/ui_cmddisp.c
@@ -0,0 +1,252 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * UI Command Dispatch File: ui_cmddisp.c
+ *
+ * This module contains routines to maintain the command table,
+ * parse and execute commands
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include <stdarg.h>
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "lib_setjmp.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_error.h"
+#include "env_subr.h"
+#include "cfe.h"
+#include "ui_command.h"
+
+/* *********************************************************************
+ * Types
+ ********************************************************************* */
+
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+static jmp_buf ui_jmpbuf; /* for getting control in exceptions */
+
+
+
+void dumplist(queue_t *qb);
+void dumplist(queue_t *qb)
+{
+ queue_t *q;
+ ui_token_t *t;
+
+ for (q = qb->q_next; q != qb; q = q->q_next) {
+
+ t = (ui_token_t *) q;
+ printf("[%s] ",&(t->token));
+ }
+ printf("\n");
+}
+
+
+
+const char *ui_errstring(int errcode)
+{
+ return cfe_errortext(errcode);
+}
+
+
+int ui_showerror(int errcode,char *tmplt,...)
+{
+ va_list marker;
+
+ va_start(marker,tmplt);
+ xvprintf(tmplt,marker);
+ va_end(marker);
+ xprintf(": %s\n",ui_errstring(errcode));
+
+ return errcode;
+}
+
+
+
+static int ui_do_one_command(queue_t *head)
+{
+ int res;
+ ui_cmdline_t cmd;
+
+ res = cmd_lookup(head, &cmd);
+
+ if (res == 0) {
+
+ res = cmd_sw_validate(&cmd,cmd.switches);
+ if (res != -1) {
+ xprintf("Invalid switch: %s\n",
+ cmd_sw_name(&cmd,res));
+ return CFE_ERR_INV_PARAM;
+ }
+
+ if (lib_setjmp(ui_jmpbuf) != 0) return -1;
+ res = (*cmd.func)(&cmd,cmd.argc-cmd.argidx,
+ &(cmd.argv[cmd.argidx]));
+ }
+ cmd_free(&cmd);
+ return res;
+}
+
+
+void ui_restart(int arg)
+{
+ if (arg == 0) arg = -1;
+
+ lib_longjmp(ui_jmpbuf,arg);
+}
+
+int ui_init_cmddisp(void)
+{
+ cmd_init();
+
+ return 0;
+}
+
+int ui_showusage(ui_cmdline_t *cmd)
+{
+ cmd_showusage(cmd);
+
+ return CFE_ERR_INV_COMMAND;
+}
+
+
+/* *********************************************************************
+ * ui_docommands_internal(head)
+ *
+ * Process (possibly multiple) commands from a list of tokens
+ *
+ * Input parameters:
+ * buf - buffer
+ *
+ * Return value:
+ * exit status of first command that failed, or null
+ ********************************************************************* */
+static int ui_docommands_internal(queue_t *head)
+{
+ queue_t cmdqueue;
+ ui_command_t *cmd;
+ int status = CMD_ERR_BLANK;
+ int term;
+
+ q_init(&cmdqueue);
+
+ /*
+ * Find all the individual commands
+ */
+
+ while ((cmd = cmd_readcommand(head))) {
+
+ if (cmd == NULL) {
+ return CMD_ERR_BLANK;
+ }
+
+ q_enqueue(&cmdqueue,(queue_t *) cmd);
+ }
+
+ /*
+ * Do each command
+ */
+
+ while ((cmd = (ui_command_t *) q_deqnext(&(cmdqueue)))) {
+ status = ui_do_one_command(&(cmd->head));
+ term = cmd->term;
+ KFREE(cmd);
+ if (status == CMD_ERR_BLANK) continue;
+
+ /*
+ * And causes us to stop at the first failure.
+ */
+ if ((term == CMD_TERM_AND) && (status != 0)) break;
+
+ /*
+ * OR causes us to stop at the first success.
+ */
+
+ if ((term == CMD_TERM_OR) && (status == 0)) break;
+
+ /*
+ * Neither AND nor OR causes us to keep chugging away.
+ */
+ }
+
+ /*
+ * Free any remaining tokens and commands that we did not do
+ */
+
+ while ((cmd = (ui_command_t *) q_deqnext(&(cmdqueue)))) {
+ cmd_free_tokens(&(cmd->head));
+ KFREE(cmd);
+ }
+
+ return status;
+}
+
+
+int ui_docommands(char *str)
+{
+ queue_t cmd_list;
+ int res;
+
+ /* Convert the command into a token list */
+ cmd_build_list(&cmd_list,str);
+
+ /* Walk the list and expand environment variables */
+ cmd_walk_and_expand(&cmd_list);
+
+ /* Process each command. This removes tokens from the list */
+ res = ui_docommands_internal(&cmd_list);
+
+ /* Free any leftover tokens. There should not be any. */
+ cmd_free_tokens(&cmd_list);
+
+ return res;
+}
diff --git a/cfe/cfe/ui/ui_command.c b/cfe/cfe/ui/ui_command.c
new file mode 100644
index 0000000..79d770f
--- /dev/null
+++ b/cfe/cfe/ui/ui_command.c
@@ -0,0 +1,990 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * UI Command Dispatch File: ui_command.c
+ *
+ * This module contains routines to maintain the command table,
+ * parse and execute commands
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include <stdarg.h>
+
+#include "lib_queue.h"
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_error.h"
+#include "env_subr.h"
+#include "cfe.h"
+
+#include "ui_command.h"
+
+#define MAX_EXPAND 16
+
+typedef struct cmdtab_s {
+ struct cmdtab_s *sibling;
+ struct cmdtab_s *child;
+ char *cmdword;
+ int (*func)(ui_cmdline_t *,int argc,char *argv[]);
+ void *ref;
+ char *help;
+ char *usage;
+ char *switches;
+} cmdtab_t;
+
+cmdtab_t *cmd_root;
+
+static void cmd_rejoin_quotes(queue_t *qb);
+
+#define myisalpha(x) (((x)>='A')&&((x)<='Z')&&((x)>='a')&&((x)<='z'))
+#define myisdigit(x) (((x)>='0')&&((x)<='9'))
+
+char *varchars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789_?";
+
+static char *tokenbreaks = " =\t\n\'\"&|;";
+static char *spacechars = " \t";
+
+
+
+static inline int is_white_space(ui_token_t *t)
+{
+ return (strchr(spacechars,t->token) != NULL);
+}
+
+int cmd_sw_value(ui_cmdline_t *cmd,char *swname,char **swvalue)
+{
+ int idx;
+
+ for (idx = 0; idx < cmd->swc; idx++) {
+ if (strcmp(swname,cmd->swv[idx].swname) == 0) {
+ *swvalue = cmd->swv[idx].swvalue;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int cmd_sw_posn(ui_cmdline_t *cmd,char *swname)
+{
+ int idx;
+
+ for (idx = 0; idx < cmd->swc; idx++) {
+ if (strcmp(swname,cmd->swv[idx].swname) == 0) {
+ return cmd->swv[idx].swidx;
+ }
+ }
+
+ return -1;
+}
+
+char *cmd_sw_name(ui_cmdline_t *cmd,int swidx)
+{
+ if ((swidx < 0) || (swidx >= cmd->swc)) return NULL;
+
+ return cmd->swv[swidx].swname;
+}
+
+
+int cmd_sw_isset(ui_cmdline_t *cmd,char *swname)
+{
+ int idx;
+
+ for (idx = 0; idx < cmd->swc; idx++) {
+ if (strcmp(swname,cmd->swv[idx].swname) == 0) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+char *cmd_getarg(ui_cmdline_t *cmd,int argnum)
+{
+ argnum += cmd->argidx;
+ if ((argnum < 0) || (argnum >= cmd->argc)) return NULL;
+ return cmd->argv[argnum];
+}
+
+void cmd_free(ui_cmdline_t *cmd)
+{
+ int idx;
+
+ for (idx = 0; idx < cmd->argc; idx++) {
+ KFREE(cmd->argv[idx]);
+ }
+
+ for (idx = 0; idx < cmd->swc; idx++) {
+ KFREE(cmd->swv[idx].swname);
+ }
+
+ cmd->argc = 0;
+ cmd->swc = 0;
+}
+
+int cmd_sw_validate(ui_cmdline_t *cmd,char *validstr)
+{
+ char *vdup;
+ char *vptr;
+ char *vnext;
+ char atype;
+ char *x;
+ int idx;
+ int valid;
+
+ if (cmd->swc == 0) return -1;
+
+ vdup = strdup(validstr);
+
+ for (idx = 0; idx < cmd->swc; idx++) {
+ vptr = vdup;
+
+ vnext = vptr;
+ valid = 0;
+
+ while (vnext) {
+
+ /*
+ * Eat the next switch description from the valid string
+ */
+ x = strchr(vptr,'|');
+ if (x) {
+ *x = '\0';
+ vnext = x+1;
+ }
+ else {
+ vnext = NULL;
+ }
+
+ /*
+ * Get the expected arg type, if any
+ */
+ x = strchr(vptr,'=');
+ if (x) {
+ atype = *(x+1);
+ *x = 0;
+ }
+ else {
+ if ((x = strchr(vptr,';'))) *x = 0;
+ atype = 0;
+ }
+
+ /*
+ * See if this matches what the user typed
+ * XXX for now, ignore the arg type processing but
+ * complain if an arg is missing.
+ */
+
+ if (strcmp(vptr,cmd->swv[idx].swname) == 0) {
+ /* Value not needed and not supplied */
+ if ((atype == 0) && (cmd->swv[idx].swvalue == NULL)) {
+ valid = 1;
+ }
+ /* value needed and supplied */
+ if ((atype != 0) && (cmd->swv[idx].swvalue != NULL)) {
+ valid = 1;
+ }
+ strcpy(vdup,validstr);
+ break;
+ }
+
+ /*
+ * Otherwise, next!
+ */
+
+ strcpy(vdup,validstr);
+ vptr = vnext;
+ }
+
+ /*
+ * If not valid, return index of bad switch
+ */
+
+ if (valid == 0) {
+ KFREE(vdup);
+ return idx;
+ }
+
+ }
+
+ /*
+ * Return -1 if everything went well. A little strange,
+ * but it's easier this way.
+ */
+
+ KFREE(vdup);
+ return -1;
+}
+
+static cmdtab_t *cmd_findword(cmdtab_t *list,char *cmdword)
+{
+ while (list) {
+ if (strcmp(cmdword,list->cmdword) == 0) return list;
+ list = list->sibling;
+ }
+
+ return NULL;
+}
+
+
+void cmd_build_cmdline(queue_t *head, ui_cmdline_t *cmd)
+{
+ ui_token_t *t;
+ ui_token_t *next;
+
+ memset(cmd, 0, sizeof(ui_cmdline_t));
+
+ t = (ui_token_t *) q_deqnext(head);
+
+ while (t != NULL) {
+ if (is_white_space(t)) {
+ /* do nothing */
+ }
+ else if (t->token != '-') {
+ if(cmd->argc < MAX_TOKENS){
+ cmd->argv[cmd->argc] = lib_strdup(&(t->token));
+ cmd->argc++;
+ }
+ /* Token is a switch */
+ }
+ else {
+ if (cmd->swc < MAX_SWITCHES) {
+ cmd->swv[cmd->swc].swname = lib_strdup(&(t->token));
+
+ if (t->qb.q_next != head) { /* more tokens */
+ next = (ui_token_t *) t->qb.q_next;
+ if (next->token == '=') { /* switch has value */
+ KFREE(t); /* Free switch name */
+ t = (ui_token_t *) q_deqnext(head); /* eat equal sign */
+ KFREE(t); /* and free it */
+ t = (ui_token_t *) q_deqnext(head); /* now have value */
+ if (t != NULL) {
+ cmd->swv[cmd->swc].swvalue = lib_strdup(&(t->token));
+ }
+ }
+ else { /* no value */
+ cmd->swv[cmd->swc].swvalue = NULL;
+ }
+ }
+ /*
+ * swidx is the index of the argument that this
+ * switch precedes. So, if you have "foo -d bar",
+ * swidx for "-d" would be 1.
+ */
+ cmd->swv[cmd->swc].swidx = cmd->argc;
+ cmd->swc++;
+ }
+ }
+ KFREE(t);
+ t = (ui_token_t *) q_deqnext(head);
+ }
+
+}
+
+int cmd_addcmd(char *command,
+ int (*func)(ui_cmdline_t *,int argc,char *argv[]),
+ void *ref,
+ char *help,
+ char *usage,
+ char *switches)
+{
+ cmdtab_t **list = &cmd_root;
+ cmdtab_t *cmd = NULL;
+ queue_t tokens;
+ queue_t *cur;
+ ui_token_t *t;
+
+ cmd_build_list(&tokens,command);
+ cur = tokens.q_next;
+
+ while (cur != &tokens) {
+ t = (ui_token_t *) cur;
+ if (!is_white_space(t)) {
+ cmd = cmd_findword(*list,&(t->token));
+ if (!cmd) {
+ cmd = KMALLOC(sizeof(cmdtab_t)+strlen(&(t->token))+1,0);
+ memset(cmd,0,sizeof(cmdtab_t));
+ cmd->cmdword = (char *) (cmd+1);
+ strcpy(cmd->cmdword,&(t->token));
+ cmd->sibling = *list;
+ *list = cmd;
+ }
+ list = &(cmd->child);
+ }
+ cur = cur->q_next;
+ }
+
+ cmd_free_tokens(&tokens);
+
+ if (!cmd) return -1;
+
+ cmd->func = func;
+ cmd->usage = usage;
+ cmd->ref = ref;
+ cmd->help = help;
+ cmd->switches = switches;
+
+ return 0;
+}
+
+
+
+static void _dumpindented(char *str,int amt)
+{
+ int idx;
+ char *dupstr;
+ char *end;
+ char *ptr;
+
+ dupstr = strdup(str);
+
+ ptr = dupstr;
+
+ while (*ptr) {
+ for (idx = 0; idx < amt; idx++) printf(" ");
+
+ end = strchr(ptr,'\n');
+
+ if (end) *end++ = '\0';
+ else end = ptr + strlen(ptr);
+
+ printf("%s\n",ptr);
+ ptr = end;
+ }
+
+ KFREE(dupstr);
+}
+
+static void _dumpswitches(char *str)
+{
+ char *switches;
+ char *end;
+ char *ptr;
+ char *semi;
+ char *newline;
+
+ switches = strdup(str);
+
+ ptr = switches;
+
+ while (*ptr) {
+ end = strchr(ptr,'|');
+ if (end) *end++ = '\0';
+ else end = ptr + strlen(ptr);
+
+ printf(" ");
+ if ((semi = strchr(ptr,';'))) {
+ *semi++ = '\0';
+ newline = strchr(semi,'\n');
+ if (newline) *newline++ = '\0';
+ printf("%-12s %s\n",ptr,semi);
+ if (newline) _dumpindented(newline,5+12+1);
+ }
+ else {
+ printf("%-12s (no information)\n",ptr);
+ }
+ ptr = end;
+ }
+
+ KFREE(switches);
+}
+
+static void _dumpcmds(cmdtab_t *cmd,int level,char **words,int verbose)
+{
+ int idx;
+ int len;
+
+ while (cmd) {
+ len = 0;
+ words[level] = cmd->cmdword;
+ if (cmd->func) {
+ for (idx = 0; idx < level; idx++) {
+ printf("%s ",words[idx]);
+ len += strlen(words[idx])+1;
+ }
+ printf("%s",cmd->cmdword);
+ len += strlen(cmd->cmdword);
+ for (idx = len; idx < 20; idx++) printf(" ");
+ printf("%s\n",cmd->help);
+ if (verbose) {
+ printf("\n");
+ _dumpindented(cmd->usage,5);
+ printf("\n");
+ _dumpswitches(cmd->switches);
+ printf("\n");
+ }
+ }
+ _dumpcmds(cmd->child,level+1,words,verbose);
+ cmd = cmd->sibling;
+ }
+}
+
+static void dumpcmds(int verbose)
+{
+ char *words[20];
+
+ _dumpcmds(cmd_root,0,words,verbose);
+}
+
+
+static void _showpossible(ui_cmdline_t *cline,cmdtab_t *cmd)
+{
+ int i;
+
+ if (cline->argidx == 0) {
+ printf("Available commands: ");
+ }
+ else {
+ printf("Available \"");
+ for (i = 0; i < cline->argidx; i++) {
+ printf("%s%s",(i == 0) ? "" : " ",cline->argv[i]);
+ }
+ printf("\" commands: ");
+ }
+
+ while (cmd) {
+ printf("%s",cmd->cmdword);
+ if (cmd->sibling) printf(", ");
+ cmd = cmd->sibling;
+ }
+
+ printf("\n");
+}
+
+static int cmd_help(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ cmdtab_t **tab;
+ cmdtab_t *cword;
+ int idx;
+
+ if (argc == 0) {
+ printf("Available commands:\n\n");
+ dumpcmds(0);
+ printf("\n");
+ printf("For more information about a command, enter 'help command-name'\n");
+ }
+ else {
+ idx = 0;
+ tab = &cmd_root;
+ cword = NULL;
+
+ for (;;) {
+ cword = cmd_findword(*tab,argv[idx]);
+ if (!cword) break;
+ if (cword->func != NULL) break;
+ idx++;
+ tab = &(cword->child);
+ if (idx >= argc) break;
+ }
+
+ if (cword == NULL) {
+ printf("No help available for '%s'.\n\n",argv[idx]);
+ printf("Type 'help' for a list of commands.\n");
+ return -1;
+ }
+
+ if (!cword->func && (idx >= argc)) {
+ printf("No help available for '%s'.\n\n",cword->cmdword);
+ printf("Type 'help' for a list of commands.\n");
+ return -1;
+ }
+
+ printf("\n SUMMARY\n\n");
+ _dumpindented(cword->help,5);
+ printf("\n USAGE\n\n");
+ _dumpindented(cword->usage,5);
+ if (cword->switches && cword->switches[0]) {
+ printf("\n OPTIONS\n\n");
+ _dumpswitches(cword->switches);
+ }
+ printf("\n");
+ }
+
+ return 0;
+}
+
+void cmd_init(void)
+{
+ cmd_root = NULL;
+
+ cmd_addcmd("help",
+ cmd_help,
+ NULL,
+ "Obtain help for CFE commands",
+ "help [command]\n\n"
+ "Without any parameters, the 'help' command will display a summary\n"
+ "of available commands. For more details on a command, type 'help'\n"
+ "and the command name.",
+ "");
+}
+
+
+int cmd_lookup(queue_t *head,ui_cmdline_t *cmd)
+{
+ cmdtab_t **tab;
+ cmdtab_t *cword;
+ int idx;
+
+ /*
+ * Reset the command line
+ */
+
+ memset(cmd,0,sizeof(ui_cmdline_t));
+
+ /*
+ * Break it up into tokens
+ */
+
+ cmd_build_cmdline(head, cmd);
+
+ if (cmd->argc == 0) return CMD_ERR_BLANK;
+
+ /*
+ * Start walking the tree looking for a function
+ * to execute.
+ */
+
+ idx = 0;
+ tab = &cmd_root;
+ cword = NULL;
+
+ for (;;) {
+ cword = cmd_findword(*tab,cmd->argv[idx]);
+ if (!cword) break;
+ if (cword->func != NULL) break;
+ idx++;
+ tab = &(cword->child);
+ if (idx >= cmd->argc) break;
+ }
+
+ cmd->argidx = idx;
+
+/* XXX - Must fix this... the error needs to walk the tree! */
+
+ if (cword == NULL) {
+ printf("Invalid command: \"%s\"\n", cmd->argv[idx]);
+ _showpossible(cmd,*tab);
+ printf("\n");
+ return CMD_ERR_INVALID;
+ }
+
+ if (!cword->func && (idx >= cmd->argc)) {
+ printf("Incomplete command: \"%s\"\n",cmd->argv[idx]);
+ _showpossible(cmd,*tab);
+ printf("\n");
+ return CMD_ERR_AMBIGUOUS;
+ }
+
+ cmd->argidx++;
+ cmd->ref = cword->ref;
+ cmd->usage = cword->usage;
+ cmd->switches = cword->switches;
+ cmd->func = cword->func;
+
+ return 0;
+}
+
+
+void cmd_showusage(ui_cmdline_t *cmd)
+{
+ printf("\n");
+ _dumpindented(cmd->usage,5);
+ printf("\n");
+ if (cmd->switches[0]) {
+ _dumpswitches(cmd->switches);
+ printf("\n");
+ }
+}
+
+
+static void cmd_eat_leading_white(queue_t *head)
+{
+ ui_token_t *t;
+
+ while (!q_isempty(head)) {
+ t = (ui_token_t *) q_getfirst(head);
+ if (is_white_space(t)) {
+ q_dequeue(&(t->qb));
+ KFREE(t);
+ }
+ else break;
+ }
+}
+
+ui_command_t *cmd_readcommand(queue_t *head)
+{
+ char *ptr;
+ int insquote = FALSE;
+ int indquote = FALSE;
+ ui_command_t *cmd;
+ int term = CMD_TERM_EOL;
+ ui_token_t *t;
+
+ cmd_eat_leading_white(head);
+
+ if (q_isempty(head)) return NULL;
+
+ cmd = (ui_command_t *) KMALLOC(sizeof(ui_command_t),0);
+ q_init(&(cmd->head));
+
+ while ((t = (ui_token_t *) q_deqnext(head))) {
+
+ ptr = &(t->token);
+
+ if (!insquote && !indquote) {
+ if ((*ptr == ';') || (*ptr == '\n')) {
+ term = CMD_TERM_SEMI;
+ break;
+ }
+ if ((*ptr == '&') && (*(ptr+1) == '&')) {
+ term = CMD_TERM_AND;
+ break;
+ }
+ if ((*ptr == '|') && (*(ptr+1) == '|')) {
+ term = CMD_TERM_OR;
+ break;
+ }
+ }
+
+ if (*ptr == '\'') {
+ insquote = !insquote;
+ }
+
+ if (!insquote) {
+ if (*ptr == '"') {
+ indquote = !indquote;
+ }
+ }
+
+ q_enqueue(&(cmd->head),&(t->qb));
+
+ }
+
+ cmd->term = term;
+
+ /* If we got out by finding a command separator, eat the separator */
+ if (term != CMD_TERM_EOL) {
+ KFREE(t);
+ }
+
+ /* Turn quoted strings back into tokens */
+
+ cmd_rejoin_quotes(&(cmd->head));
+
+ return cmd;
+}
+
+
+
+static ui_token_t *make_token(char *str,int len)
+{
+ ui_token_t *t = (ui_token_t *) KMALLOC(sizeof(ui_token_t) + len,0);
+
+ memcpy(&(t->token),str,len);
+ (&(t->token))[len] = 0;
+
+ return t;
+}
+
+void cmd_build_list(queue_t *qb,char *buf)
+{
+ char *cur = buf, *start = NULL, *fin = NULL;
+ ui_token_t *t;
+
+ q_init(qb);
+
+ start = cur;
+ while(*cur != '\0'){
+ if (*cur == '&' && *(cur + 1) != '&') {
+ /* Do nothing if we have only one & */
+ }
+ else if (*cur == '|' && *(cur + 1) != '|') {
+ /* Do nothing if we have only one | */
+ }
+ else if (((*cur == ' ')||(*cur == '\t')) &&
+ ((*(cur - 1) == ' ')||(*(cur - 1) == '\t'))) {
+ /* Make one big token for white space */
+ }
+ else {
+
+ if (strchr(tokenbreaks,*cur)) {
+ if (cur != buf) {
+ fin = cur;
+ t = make_token(start,fin-start);
+ q_enqueue(qb,&(t->qb));
+ start = cur; /* Start new token */
+ }
+ }
+ else {
+ /* If we are on a normal character but the last character was */
+ /* a special char we need to start a new token */
+
+ if ((cur > buf) && strchr(tokenbreaks,*(cur-1))) {
+ fin = cur;
+ t = make_token(start,fin-start);
+ q_enqueue(qb,&(t->qb));
+ start = cur; /* Start new token */
+ }
+ else {
+ /* If the last charecter wasn't special keep going with */
+ /* current token */
+ }
+
+
+ }
+
+ }
+ cur++;
+ }
+
+ fin = cur;
+
+ if (fin-start > 0) {
+ t = make_token(start,fin-start);
+ q_enqueue(qb,&(t->qb));
+ }
+
+ return;
+}
+
+static int is_command_separator(ui_token_t *t)
+{
+ char *string = &(t->token);
+ int sep = 0;
+
+ switch(*string){
+ case ';':
+ sep = 1;
+ break;
+ case '&':
+ if(*(string + 1) == '&')
+ sep = 1;
+ break;
+ case '|':
+ if(*(string + 1) == '|')
+ sep = 1;
+ default:
+ break;
+ }
+
+ return(sep);
+}
+
+static void cmd_append_tokens(queue_t *qb,char *str)
+{
+ queue_t *qq;
+ queue_t explist;
+
+ cmd_build_list(&explist,str);
+
+ while ((qq = q_deqnext(&explist))) {
+ q_enqueue(qb,qq);
+ }
+}
+
+static void cmd_squash_and_append(queue_t *list,queue_t *quotelist)
+{
+ int maxlen = 0;
+ queue_t *q;
+ ui_token_t *t;
+ ui_token_t *newtok;
+ char *dest;
+
+ for (q = quotelist->q_next; q != quotelist; q = q->q_next) {
+ maxlen += strlen(&(((ui_token_t *) q)->token));
+ }
+
+ newtok = KMALLOC(sizeof(ui_token_t) + maxlen,0);
+
+ dest = &(newtok->token);
+
+ while ((t = (ui_token_t *) q_deqnext(quotelist))) {
+ strcpy(dest,&(t->token));
+ dest += strlen(dest);
+ KFREE(t);
+ }
+
+ q_enqueue(list,&(newtok->qb));
+}
+
+
+static void cmd_rejoin_quotes(queue_t *qb)
+{
+ queue_t newq;
+ queue_t quotedq;
+ queue_t *q;
+ ui_token_t *t;
+ int insquote = FALSE;
+ int indquote = FALSE;
+
+ q_init(&newq);
+ q_init(&quotedq);
+
+ while ((t = (ui_token_t *) q_deqnext(qb))) {
+
+ switch (t->token) {
+ case '\'':
+ KFREE(t); /* eat the quotes */
+
+ insquote = !insquote;
+
+ if (!insquote) {
+ cmd_squash_and_append(&newq,&quotedq);
+ }
+ break;
+
+ case '"': /* eat the quotes */
+ KFREE(t);
+
+ if (insquote == FALSE) {
+ indquote = !indquote;
+ if (!indquote) {
+ cmd_squash_and_append(&newq,&quotedq);
+ }
+ }
+ break;
+
+ default:
+ if (insquote || indquote) {
+ q_enqueue(&quotedq,&(t->qb));
+ }
+ else {
+ q_enqueue(&newq,&(t->qb));
+ }
+
+ }
+ }
+
+ /*
+ * If a dangling quoted string, just tack it on the list.
+ */
+
+ if (!q_isempty(&quotedq)) {
+ cmd_squash_and_append(&newq,&quotedq);
+ }
+
+ /*
+ * Put everything back on the original list.
+ */
+
+ while ((q = q_deqnext(&newq))) {
+ q_enqueue(qb,q);
+ }
+
+
+}
+
+void cmd_walk_and_expand (queue_t *qb)
+{
+ queue_t *q;
+ queue_t newq;
+ ui_token_t *t;
+ int alias_check = TRUE;
+ int insquote = FALSE;
+ char *envstr;
+
+ q_init(&newq);
+
+ while ((t = (ui_token_t *) q_deqnext(qb))) {
+ if (t->token == '\'') {
+ alias_check = FALSE;
+ insquote = !insquote;
+ /* Check to see if we should try to expand this token */
+ }
+ else if (!insquote) {
+ if (alias_check && !strchr(tokenbreaks,t->token) &&
+ (envstr = env_getenv(&(t->token)))) {
+ /* Aliases: stick into token stream if no environment found */
+ cmd_append_tokens(&newq,envstr);
+ KFREE(t);
+ t = NULL;
+ }
+ else if (t->token == '$') {
+ /* non-aliases: remove from token stream if no env found */
+ envstr = env_getenv(&(t->token)+1);
+ if (envstr) cmd_append_tokens(&newq,envstr);
+ KFREE(t);
+ t = NULL;
+ }
+ else {
+ /* Drop down below, keep this token as-is and append */
+ }
+ }
+
+ /*
+ * If token was not removed, add it to the new queue
+ */
+
+ if (t) {
+ q_enqueue(&newq,&(t->qb));
+ alias_check = is_command_separator(t);
+ }
+
+ }
+
+ /*
+ * Put everything back on the original list.
+ */
+
+ while ((q = q_deqnext(&newq))) {
+ q_enqueue(qb,q);
+ }
+
+}
+
+void cmd_free_tokens(queue_t *list)
+{
+ queue_t *q;
+
+ while ((q = q_deqnext(list))) {
+ KFREE(q);
+ }
+}
+
diff --git a/cfe/cfe/ui/ui_devcmds.c b/cfe/cfe/ui/ui_devcmds.c
new file mode 100644
index 0000000..72ea7bb
--- /dev/null
+++ b/cfe/cfe/ui/ui_devcmds.c
@@ -0,0 +1,101 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Device Commands File: ui_devcmds.c
+ *
+ * User interface for the device manager
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "env_subr.h"
+#include "ui_command.h"
+#include "cfe.h"
+
+
+extern queue_t cfe_devices;
+
+int ui_init_devcmds(void);
+
+static int ui_cmd_devnames(ui_cmdline_t *cmd,int argc,char *argv[]);
+
+
+int ui_cmd_devnames(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ queue_t *qb;
+ cfe_device_t *dev;
+
+ xprintf("Device Name Description\n");
+ xprintf("------------------- ---------------------------------------------------------\n");
+
+ for (qb = cfe_devices.q_next; qb != &cfe_devices; qb = qb->q_next) {
+ dev = (cfe_device_t *) qb;
+
+ xprintf("%19s %s\n",dev->dev_fullname,
+ dev->dev_description);
+
+ }
+
+ return 0;
+}
+
+
+int ui_init_devcmds(void)
+{
+ cmd_addcmd("show devices",
+ ui_cmd_devnames,
+ NULL,
+ "Display information about the installed devices.",
+ "show devices\n\n"
+ "This command displays the names and descriptions of the devices\n"
+ "CFE is configured to support.",
+ "");
+
+ return 0;
+}
diff --git a/cfe/cfe/ui/ui_envcmds.c b/cfe/cfe/ui/ui_envcmds.c
new file mode 100644
index 0000000..9d69f36
--- /dev/null
+++ b/cfe/cfe/ui/ui_envcmds.c
@@ -0,0 +1,190 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Environment commands File: ui_envcmds.c
+ *
+ * User interface for environment variables
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "env_subr.h"
+#include "ui_command.h"
+#include "cfe.h"
+
+
+int ui_init_envcmds(void);
+static int ui_cmd_setenv(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_printenv(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_unsetenv(ui_cmdline_t *cmd,int argc,char *argv[]);
+
+
+
+static int ui_cmd_printenv(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char varname[80];
+ char value[256];
+ int varlen,vallen;
+ int idx;
+
+ xprintf("Variable Name Value\n");
+ xprintf("-------------------- --------------------------------------------------\n");
+
+ idx = 0;
+ for (;;) {
+ varlen = sizeof(varname);
+ vallen = sizeof(value);
+ if (env_enum(idx,varname,&varlen,value,&vallen) < 0) break;
+ xprintf("%20s %s\n",varname,value);
+ idx++;
+ }
+
+ return 0;
+
+}
+
+static int ui_cmd_setenv(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *varname;
+ char *value;
+ int roflag = ENV_FLG_NORMAL;
+ int res;
+
+ varname = cmd_getarg(cmd,0);
+
+ if (!varname) {
+ return ui_showusage(cmd);
+ }
+
+ value = cmd_getarg(cmd,1);
+ if (!value) {
+ return ui_showusage(cmd);
+ }
+
+ if (!cmd_sw_isset(cmd,"-p")) {
+ roflag = ENV_FLG_BUILTIN; /* just in memory, not NVRAM */
+ }
+
+ if (cmd_sw_isset(cmd,"-ro")) {
+ roflag = ENV_FLG_READONLY;
+ }
+
+ if ((res = env_setenv(varname,value,roflag)) == 0) {
+ if (roflag != ENV_FLG_BUILTIN) env_save();
+ }
+ else {
+ return ui_showerror(res,"Could not set environment variable '%s'",
+ varname);
+ }
+
+ return 0;
+}
+
+
+static int ui_cmd_unsetenv(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *varname;
+ int res;
+ int type;
+
+ varname = cmd_getarg(cmd,0);
+
+ if (!varname) {
+ return ui_showusage(cmd);
+ }
+
+ type = env_envtype(varname);
+
+ if ((res = env_delenv(varname)) == 0) {
+ if ((type >= 0) && (type != ENV_FLG_BUILTIN)) env_save();
+ }
+ else {
+ return ui_showerror(res,"Could not delete environment variable '%s'",
+ varname);
+ }
+
+ return 0;
+}
+
+
+
+int ui_init_envcmds(void)
+{
+
+ cmd_addcmd("setenv",
+ ui_cmd_setenv,
+ NULL,
+ "Set an environment variable.",
+ "setenv [-ro] [-p] varname value\n\n"
+ "This command sets an environment variable. By default, an environment variable\n"
+ "is stored only in memory and will not be retained across system restart.",
+ "-p;Store environment variable permanently in the NVRAM device, if present|"
+ "-ro;Causes variable to be read-only\n"
+ "(cannot be changed in the future, implies -p)");
+
+ cmd_addcmd("printenv",
+ ui_cmd_printenv,
+ NULL,
+ "Display the environment variables",
+ "printenv\n\n"
+ "This command prints a table of the environment variables and their\n"
+ "current values.",
+ "");
+
+ cmd_addcmd("unsetenv",
+ ui_cmd_unsetenv,
+ NULL,
+ "Delete an environment variable.",
+ "unsetenv varname\n\n"
+ "This command deletes an environment variable from memory and also \n"
+ "removes it from the NVRAM device (if present).",
+ "");
+
+ return 0;
+}
diff --git a/cfe/cfe/ui/ui_examcmds.c b/cfe/cfe/ui/ui_examcmds.c
new file mode 100644
index 0000000..91edeee
--- /dev/null
+++ b/cfe/cfe/ui/ui_examcmds.c
@@ -0,0 +1,713 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Memory dump commands File: ui_examcmds.c
+ *
+ * UI functions for examining data in various ways
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_error.h"
+#include "cfe_console.h"
+
+#include "ui_command.h"
+#include "cfe.h"
+#include "disasm.h"
+
+#include "addrspace.h"
+#include "exchandler.h"
+
+
+static int ui_cmd_memdump(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_memedit(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_memfill(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_disasm(ui_cmdline_t *cmd,int argc,char *argv[]);
+
+#ifdef __long64
+#define XTOI(x) xtoq(x)
+#else
+#define XTOI(x) xtoi(x)
+#endif
+
+int ui_init_examcmds(void);
+
+
+#define ATYPE_SIZE_NONE 0
+#define ATYPE_SIZE_BYTE 1
+#define ATYPE_SIZE_HALF 2
+#define ATYPE_SIZE_WORD 4
+#define ATYPE_SIZE_QUAD 8
+#define ATYPE_SIZE_MASK 0x0F
+
+#define ATYPE_TYPE_NONE 0
+#define ATYPE_TYPE_PHYS 0x10
+#define ATYPE_TYPE_KERN 0x20
+#define ATYPE_TYPE_MASK 0xF0
+
+static long prev_addr = 0; /* initialized below in ui_init_examcmds */
+static int prev_length = 256;
+static int prev_dlength = 16;
+static int prev_wtype = ATYPE_SIZE_WORD | ATYPE_TYPE_KERN;
+
+static int getaddrargs(ui_cmdline_t *cmd,int *curtype,long *addr,int *length)
+{
+ int atype = *curtype;
+ long newaddr;
+ int newlen;
+ char *x;
+ long wlen;
+
+ if (cmd_sw_isset(cmd,"-b")) {
+ atype &= ~ATYPE_SIZE_MASK;
+ atype |= ATYPE_SIZE_BYTE;
+ }
+ else if (cmd_sw_isset(cmd,"-h")) {
+ atype &= ~ATYPE_SIZE_MASK;
+ atype |= ATYPE_SIZE_HALF;
+ }
+ else if (cmd_sw_isset(cmd,"-w")) {
+ atype &= ~ATYPE_SIZE_MASK;
+ atype |= ATYPE_SIZE_WORD;
+ }
+ else if (cmd_sw_isset(cmd,"-q")) {
+ atype &= ~ATYPE_SIZE_MASK;
+ atype |= ATYPE_SIZE_QUAD;
+ }
+
+ wlen = atype & ATYPE_SIZE_MASK;
+ if (wlen == 0) wlen = 1; /* bytes are the default */
+
+ if (cmd_sw_isset(cmd,"-p")) {
+ atype &= ~ATYPE_TYPE_MASK;
+ atype |= ATYPE_TYPE_PHYS;
+ }
+ else if (cmd_sw_isset(cmd,"-v")) {
+ atype &= ~ATYPE_TYPE_MASK;
+ atype |= ATYPE_TYPE_KERN;
+ }
+
+ *curtype = atype;
+
+ if (addr) {
+ x = cmd_getarg(cmd,0);
+ if (x) {
+ if (strcmp(x,".") == 0) newaddr = *addr;
+ else {
+ /*
+ * hold on to your lunch, this is really, really bad!
+ * Make 64-bit addresses expressed as 8-digit numbers
+ * sign extend automagically. Saves typing, but is very
+ * gross.
+ */
+ int longaddr = 0;
+ longaddr = strlen(x);
+ if (memcmp(x,"0x",2) == 0) longaddr -= 2;
+ longaddr = (longaddr > 8) ? 1 : 0;
+
+ if (longaddr) newaddr = (long) xtoq(x);
+ else newaddr = (long) xtoi(x);
+ }
+ *addr = newaddr & ~(wlen - 1); /* align to natural boundary */
+ }
+ }
+
+ if (length) {
+ x = cmd_getarg(cmd,1);
+ if (x) {
+ newlen = (long) xtoi(x);
+ *length = newlen;
+ }
+ }
+
+ return 0;
+
+}
+
+static int stuffmem(long addr,int wlen,char *tail)
+{
+ char *tok;
+ int count = 0;
+ uint8_t b;
+ uint16_t h;
+ uint32_t w;
+ uint64_t q;
+ int res = 0;
+
+ addr &= ~(wlen-1);
+
+ while ((tok = gettoken(&tail))) {
+ switch (wlen) {
+ default:
+ case 1:
+ b = (uint8_t) xtoq(tok);
+ if ((res = mem_poke(addr, b, MEM_BYTE))) {
+ /*Did not edit*/
+ return res;
+ }
+ break;
+ case 2:
+ h = (uint16_t) xtoq(tok);
+ if ((res = mem_poke(addr, h, MEM_HALFWORD))) {
+ /*Did not edit*/
+ return res;
+ }
+ break;
+ case 4:
+ w = (uint32_t) xtoq(tok);
+ if ((res = mem_poke(addr, w, MEM_WORD))) {
+ /*Did not edit*/
+ return res;
+ }
+ break;
+ case 8:
+ q = (uint64_t) xtoq(tok);
+ if ((res = mem_poke(addr, q, MEM_QUADWORD))) {
+ /*Did not edit*/
+ return res;
+ }
+ break;
+ }
+
+ addr += wlen;
+ count++;
+ }
+
+ return count;
+}
+
+static int dumpmem(long addr,long dispaddr,int length,int wlen)
+{
+ int idx,x;
+ uint8_t b;
+ uint16_t h;
+ uint32_t w;
+ uint64_t q;
+ int res = 0;
+
+ /*
+ * The reason we save the line in this union is to provide the
+ * property that the dump command will only touch the
+ * memory once. This might be useful when looking at
+ * device registers.
+ */
+
+ union {
+ uint8_t bytes[16];
+ uint16_t halves[8];
+ uint32_t words[4];
+ uint64_t quads[2];
+ } line;
+
+ addr &= ~(wlen-1);
+
+ for (idx = 0; idx < length; idx += 16) {
+ xprintf("%P%c ",dispaddr+idx,(dispaddr != addr) ? '%' : ':');
+ switch (wlen) {
+ default:
+ case 1:
+ for (x = 0; x < 16; x++) {
+ if (idx+x < length) {
+ if ((res = mem_peek(&b, (addr+idx+x), MEM_BYTE))) {
+ return res;
+ }
+ line.bytes[x] = b;
+ xprintf("%02X ",b);
+ }
+ else {
+ xprintf(" ");
+ }
+ }
+ break;
+ case 2:
+ for (x = 0; x < 16; x+=2) {
+ if (idx+x < length) {
+ if ((res = mem_peek(&h, (addr+idx+x), MEM_HALFWORD))) {
+ return res;
+ }
+ line.halves[x/2] = h;
+ xprintf("%04X ",h);
+ }
+ else {
+ xprintf(" ");
+ }
+ }
+ break;
+ case 4:
+ for (x = 0; x < 16; x+=4) {
+ if (idx+x < length) {
+
+ if ((res = mem_peek(&w , (addr+idx+x), MEM_WORD))) {
+ return res;
+ }
+ line.words[x/4] = w;
+ xprintf("%08X ",w);
+ }
+ else {
+ xprintf(" ");
+ }
+ }
+ break;
+ case 8:
+ for (x = 0; x < 16; x+=8) {
+ if (idx+x < length) {
+ if ((res = mem_peek(&q, (addr+idx+x), MEM_QUADWORD))) {
+ return res;
+ }
+ line.quads[x/8] = q;
+ xprintf("%016llX ",q);
+ }
+ else {
+ xprintf(" ");
+ }
+ }
+ break;
+ }
+
+ xprintf(" ");
+ for (x = 0; x < 16; x++) {
+ if (idx+x < length) {
+ b = line.bytes[x];
+ if ((b < 32) || (b > 127)) xprintf(".");
+ else xprintf("%c",b);
+ }
+ else {
+ xprintf(" ");
+ }
+ }
+ xprintf("\n");
+ }
+
+ return 0;
+}
+
+static int ui_cmd_memedit(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ uint8_t b;
+ uint16_t h;
+ uint32_t w;
+ uint64_t q;
+
+ long addr;
+ char *vtext;
+ int wlen;
+ int count;
+ int idx = 1;
+ int stuffed = 0;
+ int res = 0;
+
+ getaddrargs(cmd,&prev_wtype,&prev_addr,NULL);
+
+ wlen = prev_wtype & ATYPE_SIZE_MASK;
+
+ vtext = cmd_getarg(cmd,idx++);
+
+ addr = prev_addr;
+
+ while (vtext) {
+ count = stuffmem(addr,wlen,vtext);
+ if (count < 0) {
+ ui_showerror(count,"Could not modify memory");
+ return count; /* error */
+ }
+ addr += count*wlen;
+ prev_addr += count*wlen;
+ stuffed += count;
+ vtext = cmd_getarg(cmd,idx++);
+ }
+
+ if (stuffed == 0) {
+ char line[256];
+ char prompt[32];
+
+ xprintf("Type '.' to exit, '-' to back up, '=' to dump memory.\n");
+ for (;;) {
+
+ addr = prev_addr;
+ if ((prev_wtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_PHYS) {
+ addr = UNCADDR(addr);
+ }
+
+ xprintf("%P%c ",prev_addr,(addr != prev_addr) ? '%' : ':');
+
+ switch (wlen) {
+ default:
+ case 1:
+ if ((res = mem_peek(&b, addr, MEM_BYTE))) {
+ return res;
+ }
+ xsprintf(prompt,"[%02X]: ", b);
+ break;
+ case 2:
+ if ((res = mem_peek(&h, addr, MEM_HALFWORD))) {
+ return res;
+ }
+ xsprintf(prompt,"[%04X]: ",h);
+ break;
+ case 4:
+ if ((res = mem_peek(&w, addr, MEM_WORD))) {
+ return res;
+ }
+ xsprintf(prompt,"[%08X]: ",w);
+ break;
+ case 8:
+ if ((res = mem_peek(&q, addr, MEM_QUADWORD))) {
+ return res;
+ }
+ xsprintf(prompt,"[%016llX]: ",q);
+ break;
+ }
+
+ console_readline(prompt,line,sizeof(line));
+ if (line[0] == '-') {
+ prev_addr -= wlen;
+ continue;
+ }
+ if (line[0] == '=') {
+ dumpmem(prev_addr,prev_addr,16,wlen);
+ continue;
+ }
+ if (line[0] == '.') {
+ break;
+ }
+ if (line[0] == '\0') {
+ prev_addr += wlen;
+ continue;
+ }
+ count = stuffmem(addr,wlen,line);
+ if (count < 0) return count;
+ if (count == 0) break;
+ prev_addr += count*wlen;
+ }
+ }
+
+ return 0;
+}
+
+static int ui_cmd_memfill(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ long addr;
+ char *atext;
+ int wlen;
+ int idx = 2;
+ int len;
+ uint64_t pattern;
+ uint8_t *b_ptr;
+ uint16_t *h_ptr;
+ uint32_t *w_ptr;
+ uint64_t *q_ptr;
+ int res;
+
+ getaddrargs(cmd,&prev_wtype,&prev_addr,&len);
+
+ atext = cmd_getarg(cmd,idx++);
+ if (!atext) return ui_showusage(cmd);
+ pattern = xtoq(atext);
+
+ addr = prev_addr;
+
+ if ((prev_wtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_PHYS) {
+ addr = UNCADDR(addr);
+ }
+
+ wlen = prev_wtype & ATYPE_SIZE_MASK;
+
+ switch (wlen) {
+ case 1:
+ b_ptr = (uint8_t *) addr;
+ while (len > 0) {
+ if ((res = mem_poke( ((long)(b_ptr)), pattern, MEM_BYTE))) {
+ /*Did not edit*/
+ return 0;
+ }
+ b_ptr++;
+ len--;
+ }
+ break;
+ case 2:
+ h_ptr = (uint16_t *) addr;
+ while (len > 0) {
+ if ((res = mem_poke( ((long)(h_ptr)), pattern, MEM_HALFWORD))) {
+ return 0;
+ }
+ h_ptr++;
+ len--;
+ }
+ break;
+ case 4:
+ w_ptr = (uint32_t *) addr;
+ while (len > 0) {
+ if ((res = mem_poke( ((long)(w_ptr)), pattern, MEM_WORD))) {
+ return -1;
+ }
+ w_ptr++;
+ len--;
+ }
+ break;
+ case 8:
+ q_ptr = (uint64_t *) addr;
+ while (len > 0) {
+ if ((res = mem_poke( ((long)(q_ptr)), pattern, MEM_QUADWORD))) {
+ return 0;
+ }
+ q_ptr++;
+ len--;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+
+#define FILL(ptr,len,pattern) printf("Pattern: %016llX\n",pattern); \
+ for (idx = 0; idx < len; idx++) ptr[idx] = pattern
+#define CHECK(ptr,len,pattern) for (idx = 0; idx < len; idx++) { \
+ if (ptr[idx]!=pattern) {printf("Mismatch at %016llX: Expected %016llX got %016llX", \
+ (uint64_t) (uintptr_t) &(ptr[idx]),pattern,ptr[idx]); \
+ error = 1; loopmode = 0;break;} \
+ }
+
+#define MEMTEST(ptr,len,pattern) if (!error) { FILL(ptr,len,pattern) ; CHECK(ptr,len,pattern); }
+
+static int ui_cmd_memtest(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ long addr = 0;
+ int len = 0;
+ int wtype = 0;
+ int wlen;
+ int idx = 0;
+ uint64_t *ptr;
+ int error = 0;
+ int loopmode = 0;
+ int pass =0;
+
+ getaddrargs(cmd,&wtype,&addr,&len);
+
+ wlen = 8;
+ addr &= ~(wlen-1);
+
+ if ((prev_wtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_PHYS) {
+ addr = UNCADDR(addr);
+ }
+
+ if (cmd_sw_isset(cmd,"-loop")) {
+ loopmode = 1;
+ }
+
+ len /= wlen;
+
+ ptr = (uint64_t *) addr;
+ pass = 0;
+ for (;;) {
+ if (loopmode) {
+ printf("Pass %d\n",pass);
+ if (console_status()) break;
+ }
+ MEMTEST(ptr,len,(idx*8));
+ MEMTEST(ptr,len, 0);
+ MEMTEST(ptr,len,0xFFFFFFFFFFFFFFFF);
+ MEMTEST(ptr,len,0x5555555555555555);
+ MEMTEST(ptr,len,0xAAAAAAAAAAAAAAAA);
+ MEMTEST(ptr,len,0xFF00FF00FF00FF00);
+ MEMTEST(ptr,len,0x00FF00FF00FF00FF);
+ if (!loopmode) break;
+ pass++;
+ }
+
+ return 0;
+}
+
+static int ui_cmd_memdump(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ long addr;
+ int res;
+
+ getaddrargs(cmd,&prev_wtype,&prev_addr,&prev_length);
+
+ addr = prev_addr;
+ if ((prev_wtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_PHYS) {
+ addr = UNCADDR(addr);
+ }
+
+ res = dumpmem(addr,
+ prev_addr,
+ prev_length,
+ prev_wtype & ATYPE_SIZE_MASK);
+
+ if (res < 0) {
+ ui_showerror(res,"Could not display memory");
+ }
+ else {
+ prev_addr += prev_length;
+ }
+
+ return res;
+}
+
+static int ui_cmd_disasm(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ long addr;
+ char buf[512];
+ int idx;
+ uint32_t inst;
+ int res;
+
+ getaddrargs(cmd,&prev_wtype,&prev_addr,&prev_dlength);
+
+ prev_addr &= ~3;
+
+ addr = prev_addr;
+ if ((prev_wtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_PHYS) {
+ addr = UNCADDR(addr);
+ }
+
+ for (idx = 0; idx < prev_dlength; idx++) {
+ if ((res = mem_peek(&inst, addr, MEM_WORD))) {
+ ui_showerror(res,"Could not disassemble memory");
+ return res;
+ }
+ disasm_inst(buf,sizeof(buf),inst,(uint64_t) prev_addr);
+ xprintf("%P%c %08x %s\n",prev_addr,(addr != prev_addr) ? '%' : ':',inst,buf);
+ addr += 4;
+ prev_addr += 4;
+ }
+
+ return 0;
+}
+
+int ui_init_examcmds(void)
+{
+ cmd_addcmd("u",
+ ui_cmd_disasm,
+ NULL,
+ "Disassemble instructions.",
+ "u [addr [length]]\n\n"
+ "This command disassembles instructions at the specified address.\n"
+ "CFE will display standard register names and symbolic names for\n"
+ "certain CP0 registers. The 'u' command remembers the last address\n"
+ "that was disassembled so you can enter 'u' again with no parameters\n"
+ "to continue a previous request.\n",
+ "-p;Address is an uncached physical address|"
+ "-v;Address is a kernel virtual address");
+
+
+ cmd_addcmd("d",
+ ui_cmd_memdump,
+ NULL,
+ "Dump memory.",
+ "d [-b|-h|-w|-q] [addr [length]]\n\n"
+ "This command displays data from memory as bytes, halfwords, words,\n"
+ "or quadwords. ASCII text, if present, will appear to the right of\n"
+ "the hex data. The dump command remembers the previous word size,\n"
+ "dump length and last displayed address, so you can enter 'd' again\n"
+ "to continue a previous dump request.",
+ "-b;Dump memory as bytes|"
+ "-h;Dump memory as halfwords (16-bits)|"
+ "-w;Dump memory as words (32-bits)|"
+ "-q;Dump memory as quadwords (64-bits)|"
+ "-p;Address is an uncached physical address|"
+ "-v;Address is a kernel virtual address");
+
+
+ cmd_addcmd("e",
+ ui_cmd_memedit,
+ NULL,
+ "Modify contents of memory.",
+ "e [-b|-h|-w|-q] [addr [data...]]\n\n"
+ "This command modifies the contents of memory. If you do not specify\n"
+ "data on the command line, CFE will prompt for it. When prompting for\n"
+ "data you may enter '-' to back up, '=' to dump memory at the current\n"
+ "location, or '.' to exit edit mode.",
+ "-b;Edit memory as bytes|"
+ "-h;Edit memory as halfwords (16-bits)|"
+ "-w;Edit memory as words (32-bits)|"
+ "-q;Edit memory as quadwords (64-bits)|"
+ "-p;Address is an uncached physical address|"
+ "-v;Address is a kernel virtual address");
+
+ cmd_addcmd("f",
+ ui_cmd_memfill,
+ NULL,
+ "Fill contents of memory.",
+ "f [-b|-h|-w|-q] addr length pattern\n\n"
+ "This command modifies the contents of memory. You can specify the\n"
+ "starting address, length, and pattern of data to fill (in hex)\n",
+ "-b;Edit memory as bytes|"
+ "-h;Edit memory as halfwords (16-bits)|"
+ "-w;Edit memory as words (32-bits)|"
+ "-q;Edit memory as quadwords (64-bits)|"
+ "-p;Address is an uncached physical address|"
+ "-v;Address is a kernel virtual address");
+
+ cmd_addcmd("memtest",
+ ui_cmd_memtest,
+ NULL,
+ "Test memory.",
+ "memtest [options] addr length\n\n"
+ "This command tests memory. It is a very crude test, so don't\n"
+ "rely on it for anything really important. Addr and length are in hex\n",
+ "-p;Address is an uncached physical address|"
+ "-v;Address is a kernel virtual address|"
+ "-loop;Loop till keypress");
+
+
+ prev_addr = KERNADDR(0);
+
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cfe/cfe/ui/ui_flash.c b/cfe/cfe/ui/ui_flash.c
new file mode 100644
index 0000000..d3ce7c1
--- /dev/null
+++ b/cfe/cfe/ui/ui_flash.c
@@ -0,0 +1,554 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Flash Update commands File: ui_flash.c
+ *
+ * The routines in this file are used for updating the
+ * flash with new firmware.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_ioctl.h"
+#include "cfe_timer.h"
+#include "cfe_error.h"
+
+#include "ui_command.h"
+#include "cfe.h"
+
+#include "cfe_fileops.h"
+#include "cfe_boot.h"
+#include "bsp_config.h"
+
+#include "cfe_loader.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+#include "net_api.h"
+
+#include "cfe_flashimage.h"
+
+#include "addrspace.h"
+#include "url.h"
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+/*
+ * Of course, these things really belong somewhere else.
+ */
+
+#define FLASH_STAGING_BUFFER CFG_FLASH_STAGING_BUFFER_ADDR
+#ifdef _FLASHPROG_
+#define FLASH_STAGING_BUFFER_SIZE (1024*1024*16)
+#else
+#define FLASH_STAGING_BUFFER_SIZE CFG_FLASH_STAGING_BUFFER_SIZE
+#endif
+
+
+/* *********************************************************************
+ * Exerns
+ ********************************************************************* */
+
+extern int cfe_iocb_dispatch(cfe_iocb_t *iocb);
+
+int ui_init_flashcmds(void);
+static int ui_cmd_flash(ui_cmdline_t *cmd,int argc,char *argv[]);
+
+
+
+/* *********************************************************************
+ * ui_init_flashcmds()
+ *
+ * Initialize the flash commands, add them to the table.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0 if ok, else error
+ ********************************************************************* */
+
+int ui_init_flashcmds(void)
+{
+ cmd_addcmd("flash",
+ ui_cmd_flash,
+ NULL,
+ "Update a flash memory device",
+ "flash [options] filename [flashdevice]\n\n"
+ "Copies data from a source file name or device to a flash memory device.\n"
+ "The source device can be a disk file (FAT filesystem), a remote file\n"
+ "(TFTP) or a flash device. The destination device may be a flash or eeprom.\n"
+#if !CFG_EMBEDDED_PIC
+ "If the destination device is your boot flash (usually flash0), the flash\n"
+ "command will restart the firmware after the flash update is complete\n"
+#endif
+ "",
+ "-noerase;Don't erase flash before writing|"
+ "-offset=*;Begin programming at this offset in the flash device|"
+ "-size=*;Size of source device when programming from flash to flash|"
+ "-noheader;Override header verification, flash binary without checking");
+
+
+ return 0;
+}
+
+/* *********************************************************************
+ * flash_crc32(buf,len)
+ *
+ * Yes, this is an Ethernet CRC. I'm lazy.
+ *
+ * Input parameters:
+ * buf - buffer to CRC
+ * len - length of data
+ *
+ * Return value:
+ * CRC-32
+ ********************************************************************* */
+
+#define CRC32_POLY 0xEDB88320UL /* CRC-32 Poly */
+static unsigned int
+flash_crc32(const unsigned char *databuf, unsigned int datalen)
+{
+ unsigned int idx, bit, data, crc = 0xFFFFFFFFUL;
+
+ for (idx = 0; idx < datalen; idx++) {
+ for (data = *databuf++, bit = 0; bit < 8; bit++, data >>= 1) {
+ crc = (crc >> 1) ^ (((crc ^ data) & 1) ? CRC32_POLY : 0);
+ }
+ }
+
+ return crc;
+}
+
+/* *********************************************************************
+ * flash_validate(ptr)
+ *
+ * Validate the flash header to make sure we can program it.
+ *
+ * Input parameters:
+ * ptr - pointer to flash header
+ * outptr - pointer to data that we should program
+ * outsize - size of data we should program
+ *
+ * Return value:
+ * 0 if ok
+ * else error occured
+ ********************************************************************* */
+
+#define GET32(x) (((uint32_t) (x[0] << 24)) | \
+ ((uint32_t) (x[1] << 16)) | \
+ ((uint32_t) (x[2] << 8)) | \
+ ((uint32_t) (x[3] << 0)))
+
+static int flash_validate(uint8_t *ptr,int insize,uint8_t **outptr,int *outsize)
+{
+ cfe_flashimage_t *hdr = (cfe_flashimage_t *) ptr;
+ uint32_t size;
+ uint32_t flags;
+ uint32_t hdrcrc;
+ uint32_t calccrc;
+
+ if (memcmp(hdr->seal,CFE_IMAGE_SEAL,sizeof(hdr->seal)) != 0) {
+ printf("Invalid header seal. This is not a CFE flash image.\n");
+ return -1;
+ }
+
+ printf("Flash image contains CFE version %d.%d.%d for board '%s'\n",
+ hdr->majver,hdr->minver,hdr->ecover,hdr->boardname);
+
+ size = GET32(hdr->size);
+ flags = GET32(hdr->flags);
+ hdrcrc = GET32(hdr->crc);
+ printf("Flash image is %d bytes, flags %08X, CRC %08X\n",size,flags,hdrcrc);
+
+ if (strcmp(CFG_BOARDNAME,hdr->boardname) != 0) {
+ printf("This flash image is not appropriate for board type '%s'\n",CFG_BOARDNAME);
+ return -1;
+ }
+
+ if ((size == 0) || (size > FLASH_STAGING_BUFFER_SIZE) ||
+ ((size + sizeof(cfe_flashimage_t)) < insize)) {
+ printf("Flash image size is bogus!\n");
+ return -1;
+ }
+
+ calccrc = flash_crc32(ptr + sizeof(cfe_flashimage_t),size);
+
+ if (calccrc != hdrcrc) {
+ printf("CRC is incorrect. Calculated CRC is %08X\n",calccrc);
+ return -1;
+ }
+
+ *outptr = ptr + sizeof(cfe_flashimage_t);
+ *outsize = size;
+ return 0;
+}
+
+/* *********************************************************************
+ * ui_cmd_flash(cmd,argc,argv)
+ *
+ * The 'flash' command lives here. Program the boot flash,
+ * or if a device name is specified, program the alternate
+ * flash device.
+ *
+ * Input parameters:
+ * cmd - command table entry
+ * argc,argv - parameters
+ *
+ * Return value:
+ * 0 if ok
+ * else error
+ ********************************************************************* */
+
+
+static int ui_cmd_flash(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ uint8_t *ptr;
+ int fh;
+ int res;
+#if !CFG_EMBEDDED_PIC
+ int retlen;
+#endif
+ char *fname;
+ char *flashdev;
+ cfe_loadargs_t la;
+ int amtcopy;
+ int devtype;
+ int srcdevtype;
+ int chkheader;
+ int sfd;
+ int copysize;
+ flash_info_t flashinfo;
+ int offset = 0;
+ int noerase = 0;
+ char *x;
+ int size = 0;
+
+ /*
+ * Get the address of the staging buffer. We can't
+ * allocate the space from the heap to store the
+ * new flash image, because the heap may not be big
+ * enough. So, grab some unallocated memory
+ * at the 1MB line (we could also calculate
+ * something, but this will do for now).
+ * We assume the flash will be somewhere between
+ * 1KB (yeah, right) and 4MB.
+ */
+
+#if CFG_RUNFROMKSEG0
+ ptr = (uint8_t *) KERNADDR(FLASH_STAGING_BUFFER);
+#else
+ ptr = (uint8_t *) UNCADDR(FLASH_STAGING_BUFFER);
+#endif
+
+ /*
+ * Parse command line parameters
+ */
+
+ fname = cmd_getarg(cmd,0);
+
+ if (!fname) {
+ return ui_showusage(cmd);
+ }
+
+ flashdev = cmd_getarg(cmd,1);
+ if (!flashdev) flashdev = "flash0.0";
+
+ /*
+ * Make sure it's a flash device.
+ */
+
+ res = cfe_getdevinfo(flashdev);
+ if (res < 0) {
+ return ui_showerror(CFE_ERR_DEVNOTFOUND,flashdev);
+ }
+
+ devtype = res & CFE_DEV_MASK;
+
+ if ((res != CFE_DEV_FLASH) && (res != CFE_DEV_NVRAM)) {
+ xprintf("Device '%s' is not a flash or eeprom device.\n",flashdev);
+ return CFE_ERR_INV_PARAM;
+ }
+
+ /*
+ * We shouldn't really allow this, but there are some circumstances
+ * where you might want to bypass the header check and shoot
+ * yourself in the foot.
+ * Switch normally not supplied, so chkheader will be TRUE.
+ */
+
+ chkheader = !cmd_sw_isset(cmd,"-noheader");
+
+ /*
+ * Check for some obscure options here.
+ */
+
+ noerase = cmd_sw_isset(cmd,"-noerase");
+
+ if (cmd_sw_value(cmd,"-offset",&x)) {
+ offset = atoi(x);
+ }
+
+ if (cmd_sw_value(cmd,"-size",&x)) {
+ size = atoi(x);
+ }
+
+ /*
+ * Read the new flash image from the source device
+ */
+
+ srcdevtype = cfe_getdevinfo(fname) & CFE_DEV_MASK;
+
+ xprintf("Reading %s: ",fname);
+
+ switch (srcdevtype) {
+ case CFE_DEV_FLASH:
+ sfd = cfe_open(fname);
+ if (sfd < 0) {
+ return ui_showerror(sfd,"Could not open source device");
+ }
+ memset(ptr,0xFF,FLASH_STAGING_BUFFER_SIZE);
+
+ /*
+ * If the flash device can be used for NVRAM,
+ * then the max size of or flash is the
+ * offset of the flash info. Otherwise
+ * it is the full staging buffer size.
+ * XXX: if it's larger, we lose.
+ */
+
+ if (cfe_ioctl(sfd,IOCTL_FLASH_GETINFO,
+ (unsigned char *) &flashinfo,
+ sizeof(flash_info_t),
+ &res,0) != 0) {
+ flashinfo.flash_size = FLASH_STAGING_BUFFER_SIZE;
+ }
+
+ if (size > 0) {
+ xprintf("(size=0x%X) ",size);
+ }
+ else {
+ size = flashinfo.flash_size;
+ }
+
+ /* Make sure we don't overrun the staging buffer */
+
+ if (size > FLASH_STAGING_BUFFER_SIZE) {
+ size = FLASH_STAGING_BUFFER_SIZE;
+ }
+
+ /* Read the flash device here. */
+
+ res = cfe_read(sfd,ptr,size);
+
+ cfe_close(sfd);
+ if (res < 0) {
+ return ui_showerror(res,"Could not read from flash");
+ }
+ chkheader = FALSE; /* no header to check */
+ /*
+ * Search for non-0xFF byte at the end. This will work because
+ * flashes get erased to all FF's, we pre-fill our buffer to FF's,
+ */
+ while (res > 0) {
+ if (ptr[res-1] != 0xFF) break;
+ res--;
+ }
+ break;
+
+ case CFE_DEV_SERIAL:
+ la.la_filesys = "raw";
+ la.la_filename = NULL;
+ la.la_device = fname;
+ la.la_address = (intptr_t) ptr;
+ la.la_options = 0;
+ la.la_maxsize = FLASH_STAGING_BUFFER_SIZE;
+ la.la_flags = LOADFLG_SPECADDR;
+
+ res = cfe_load_program("srec",&la);
+
+ if (res < 0) {
+ ui_showerror(res,"Failed.");
+ return res;
+ }
+ break;
+
+ default:
+
+ res = ui_process_url(fname, cmd, &la);
+ if (res < 0) {
+ ui_showerror(res,"Invalid file name %s",fname);
+ return res;
+ }
+
+ la.la_address = (intptr_t) ptr;
+ la.la_options = 0;
+ la.la_maxsize = FLASH_STAGING_BUFFER_SIZE;
+ la.la_flags = LOADFLG_SPECADDR;
+
+ res = cfe_load_program("raw",&la);
+
+ if (res < 0) {
+ ui_showerror(res,"Failed.");
+ return res;
+ }
+ break;
+
+ }
+
+ xprintf("Done. %d bytes read\n",res);
+
+ copysize = res;
+
+ /*
+ * Verify the header and file's CRC.
+ */
+ if (chkheader) {
+ if (flash_validate(ptr,res,&ptr,&copysize) < 0) return -1;
+ }
+
+ if (copysize == 0) return 0; /* 0 bytes, don't flash */
+
+ /*
+ * Open the destination flash device.
+ */
+
+ fh = cfe_open(flashdev);
+ if (fh < 0) {
+ xprintf("Could not open device '%s'\n",flashdev);
+ return CFE_ERR_DEVNOTFOUND;
+ }
+
+ if (cfe_ioctl(fh,IOCTL_FLASH_GETINFO,
+ (unsigned char *) &flashinfo,
+ sizeof(flash_info_t),
+ &res,0) == 0) {
+ /* Truncate write if source size is greater than flash size */
+ if ((copysize + offset) > flashinfo.flash_size) {
+ copysize = flashinfo.flash_size;
+ }
+ }
+
+ /*
+ * If overwriting the boot flash, we need to use the special IOCTL
+ * that will force a reboot after writing the flash.
+ */
+
+ if (flashinfo.flash_base == 0x1FC00000) { /* XXX MIPS-SPECIFIC */
+#if CFG_EMBEDDED_PIC
+ xprintf("\n\n** DO NOT TURN OFF YOUR MACHINE UNTIL THE FLASH UPDATE COMPLETES!! **\n\n");
+#else
+#if CFG_NETWORK
+ if (net_getparam(NET_DEVNAME)) {
+ xprintf("Closing network.\n");
+ net_uninit();
+ }
+#endif
+ xprintf("Rewriting boot flash device '%s'\n",flashdev);
+ xprintf("\n\n**DO NOT TURN OFF YOUR MACHINE UNTIL IT REBOOTS!**\n\n");
+ cfe_ioctl(fh,IOCTL_FLASH_WRITE_ALL, ptr,copysize,&retlen,0);
+ /* should not return */
+ return CFE_ERR;
+#endif
+ }
+
+ /*
+ * Otherwise: it's not the flash we're using right
+ * now, so we can be more verbose about things, and
+ * more importantly, we can return to the command
+ * prompt without rebooting!
+ */
+
+ /*
+ * Erase the flash, if the device requires it. Our new flash
+ * driver does the copy/merge/erase for us.
+ */
+
+ if (!noerase) {
+ if ((devtype == CFE_DEV_FLASH) && !(flashinfo.flash_flags & FLASH_FLAG_NOERASE)) {
+ flash_range_t range;
+ range.range_base = offset;
+ range.range_length = copysize;
+ xprintf("Erasing flash...");
+ if (cfe_ioctl(fh,IOCTL_FLASH_ERASE_RANGE,
+ (uint8_t *) &range,sizeof(range),NULL,0) != 0) {
+ printf("Failed to erase the flash\n");
+ cfe_close(fh);
+ return CFE_ERR_IOERR;
+ }
+ }
+ }
+
+ /*
+ * Program the flash
+ */
+
+ xprintf("Programming...");
+
+ amtcopy = cfe_writeblk(fh,offset,ptr,copysize);
+
+ if (copysize == amtcopy) {
+ xprintf("done. %d bytes written\n",amtcopy);
+ res = 0;
+ }
+ else {
+ ui_showerror(amtcopy,"Failed.");
+ res = CFE_ERR_IOERR;
+ }
+
+ /*
+ * done!
+ */
+
+ cfe_close(fh);
+
+ return res;
+}
+
diff --git a/cfe/cfe/ui/ui_loadcmds.c b/cfe/cfe/ui/ui_loadcmds.c
new file mode 100644
index 0000000..a1df159
--- /dev/null
+++ b/cfe/cfe/ui/ui_loadcmds.c
@@ -0,0 +1,366 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Program Loader commands File: ui_loadcmds.c
+ *
+ * User interface for program loader
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_devfuncs.h"
+
+#include "ui_command.h"
+#include "cfe.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+#include "net_api.h"
+
+#include "cfe_fileops.h"
+#include "cfe_boot.h"
+
+#include "bsp_config.h"
+#include "cfe_loader.h"
+#include "cfe_autoboot.h"
+
+#include "url.h"
+
+
+int ui_init_loadcmds(void);
+static int ui_cmd_load(ui_cmdline_t *cmd,int argc,char *argv[]);
+
+#if CFG_NETWORK
+static int ui_cmd_save(ui_cmdline_t *cmd,int argc,char *argv[]);
+#endif
+
+static int ui_cmd_autoboot(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_boot(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_batch(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_go(ui_cmdline_t *cmd,int argc,char *argv[]);
+
+
+extern cfe_loadargs_t cfe_loadargs;
+
+static long getaddr(char *str)
+{
+ /*
+ * hold on to your lunch, this is really, really bad!
+ * Make 64-bit addresses expressed as 8-digit numbers
+ * sign extend automagically. Saves typing, but is very
+ * gross. Not very portable, either.
+ */
+ int longaddr = 0;
+ long newaddr;
+
+ longaddr = strlen(str);
+ if (memcmp(str,"0x",2) == 0) longaddr -= 2;
+ longaddr = (longaddr > 8) ? 1 : 0;
+
+ if (longaddr) newaddr = (long) xtoq(str);
+ else newaddr = (long) xtoi(str);
+
+ return newaddr;
+}
+
+
+
+int ui_init_loadcmds(void)
+{
+
+#if CFG_NETWORK
+ cmd_addcmd("save",
+ ui_cmd_save,
+ NULL,
+ "Save a region of memory to a remote file via TFTP",
+ "save [-options] host:filename startaddr length\n\n",
+ "");
+#endif
+
+ cmd_addcmd("load",
+ ui_cmd_load,
+ NULL,
+ "Load an executable file into memory without executing it",
+ "load [-options] host:filename|dev:filename\n\n"
+ "This command loads an executable file into memory, but does not\n"
+ "execute it. It can be used for loading data files, overlays or\n"
+ "other programs needed before the 'boot' command is used. By\n"
+ "default, 'load' will load a raw binary at virtual address 0x20000000.",
+ "-elf;Load the file as an ELF executable|"
+ "-srec;Load the file as ASCII S-records|"
+ "-raw;Load the file as a raw binary|"
+#if CFG_ZLIB
+ "-z;Load compessed file|"
+#endif
+ "-loader=*;Specify CFE loader name|"
+ "-tftp;Load the file using the TFTP protocol|"
+ "-fatfs;Load the file from a FAT file system|"
+ "-rawfs;Load the file from an unformatted file system|"
+#if (CFG_TCP) && (CFG_HTTPFS)
+ "-http;Load the file using the HTTP protocol|"
+#endif
+ "-fs=*;Specify CFE file system name|"
+ "-max=*;Specify the maximum number of bytes to load (raw only)|"
+ "-addr=*;Specify the load address (hex) (raw only)");
+
+ cmd_addcmd("boot",
+ ui_cmd_boot,
+ NULL,
+ "Load an executable file into memory and execute it",
+ "boot [-options] host:filename|dev:filename\n\n"
+ "This command loads and executes a program from a boot device\n"
+ "By default, 'boot' will load a raw binary at virtual \n"
+ "address 0x20000000 and then jump to that address",
+ "-elf;Load the file as an ELF executable|"
+ "-srec;Load the file as ASCII S-records|"
+ "-raw;Load the file as a raw binary|"
+#if CFG_ZLIB
+ "-z;Load compessed file|"
+#endif
+ "-loader=*;Specify CFE loader name|"
+ "-tftp;Load the file using the TFTP protocol|"
+ "-fatfs;Load the file from a FAT file system|"
+ "-rawfs;Load the file from an unformatted file system|"
+#if (CFG_TCP) && (CFG_HTTPFS)
+ "-http;Load the file using the HTTP protocol|"
+#endif
+ "-fs=*;Specify CFE file system name|"
+ "-max=*;Specify the maximum number of bytes to load (raw only)|"
+ "-addr=*;Specify the load address (hex) (raw only)|"
+ "-noclose;Don't close network link before executing program");
+
+ cmd_addcmd("go",
+ ui_cmd_go,
+ NULL,
+ "Start a previously loaded program.",
+ "go [address]\n\n"
+ "The 'go' command will start a program previously loaded with \n"
+ "the 'load' command. You can override the start address by"
+ "specifying it as a parameter to the 'go' command.",
+ "-noclose;Don't close network link before executing program");
+
+ cmd_addcmd("batch",
+ ui_cmd_batch,
+ NULL,
+ "Load a batch file into memory and execute it",
+ "batch [-options] host:filename|dev:filename\n\n"
+ "This command loads and executes a batch file from a boot device",
+#if CFG_ZLIB
+ "-z;Load compessed file|"
+#endif
+ "-tftp;Load the file using the TFTP protocol|"
+ "-fatfs;Load the file from a FAT file system|"
+ "-rawfs;Load the file from an unformatted file system|"
+ "-fs=*;Specify CFE file system name");
+
+
+ cmd_addcmd("autoboot",
+ ui_cmd_autoboot,
+ NULL,
+ "Automatic system bootstrap.",
+ "autoboot [dev]\n\n"
+ "The 'autoboot' command causes an automatic system bootstrap from\n"
+ "a predefined list of devices and boot files. This list is \n"
+ "specific to the board and port of CFE. To try autobooting from\n"
+ "a specific device, you can specify the CFE device name on the command line.",
+ "-forever;Loop over devices until boot is successful|"
+ "-interruptible;Scan console between devices, drop to prompt if key pressed");
+
+ return 0;
+}
+
+
+static int ui_cmd_autoboot(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int res;
+ char *x;
+ int flags = 0;
+
+ if (cmd_sw_isset(cmd,"-forever")) flags |= CFE_AUTOFLG_TRYFOREVER;
+ if (cmd_sw_isset(cmd,"-interruptible")) flags |= CFE_AUTOFLG_POLLCONSOLE;
+
+ x = cmd_getarg(cmd,0);
+ res = cfe_autoboot(x,flags);
+
+ return res;
+}
+
+static int ui_cmd_go(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *arg;
+
+ arg = cmd_getarg(cmd,0);
+ if (arg) {
+ cfe_loadargs.la_entrypt = getaddr(arg);
+ }
+
+ if (cmd_sw_isset(cmd,"-noclose")) {
+ cfe_loadargs.la_flags |= LOADFLG_NOCLOSE;
+ }
+
+ cfe_go(&cfe_loadargs);
+
+ return 0;
+}
+
+
+
+static int ui_cmd_bootcommon(ui_cmdline_t *cmd,int argc,char *argv[],int flags)
+{
+ int res;
+ char *arg;
+ cfe_loadargs_t *la = &cfe_loadargs;
+ char copy[200];
+
+ la->la_flags = flags;
+
+ arg = cmd_getarg(cmd,0);
+ strncpy(copy,arg,sizeof(copy));
+
+ if (!arg) {
+ xprintf("No program name specified\n");
+ return -1;
+ }
+
+ res = ui_process_url(arg,cmd,la);
+ if (res < 0) return res;
+
+ /*
+ * Pick up the remaining command line parameters for use as
+ * arguments to the loaded program.
+ */
+
+ la->la_options = cmd_getarg(cmd,1);
+
+ /*
+ * Note: we might not come back here if we really launch the program.
+ */
+
+ xprintf("Loader:%s Filesys:%s Dev:%s File:%s Options:%s\n",
+ la->la_loader,la->la_filesys,la->la_device,la->la_filename,la->la_options);
+
+ res = cfe_boot(la->la_loader,la);
+
+ /*
+ * Give the bad news.
+ */
+
+ if (res < 0) xprintf("Could not load %s: %s\n",copy,cfe_errortext(res));
+
+ return res;
+}
+
+
+static int ui_cmd_load(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int flags = LOADFLG_NOISY;
+
+ return ui_cmd_bootcommon(cmd,argc,argv,flags);
+}
+
+
+
+
+static int ui_cmd_boot(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int flags = LOADFLG_NOISY | LOADFLG_EXECUTE;
+
+ return ui_cmd_bootcommon(cmd,argc,argv,flags);
+}
+
+static int ui_cmd_batch(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int flags = LOADFLG_NOISY | LOADFLG_EXECUTE | LOADFLG_BATCH;
+
+ return ui_cmd_bootcommon(cmd,argc,argv,flags);
+}
+
+#if CFG_NETWORK
+static int ui_cmd_save(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *x;
+ uint8_t *start,*end;
+ int len;
+ char *fname;
+ int res;
+
+ fname = cmd_getarg(cmd,0);
+
+ if ((x = cmd_getarg(cmd,1))) {
+ start = (uint8_t *) getaddr(x);
+ }
+ else {
+ return ui_showusage(cmd);
+ }
+
+ if ((x = cmd_getarg(cmd,2))) {
+ len = xtoi(x);
+ }
+ else {
+ return ui_showusage(cmd);
+ }
+
+ end = start+len;
+
+ res = cfe_savedata("tftp","",fname,start,end);
+
+ if (res < 0) {
+ return ui_showerror(res,"Could not dump data to network");
+ }
+ else {
+ xprintf("%d bytes written to %s\n",res,fname);
+ }
+
+ return 0;
+}
+#endif
+
+
+
+
diff --git a/cfe/cfe/ui/ui_memcmds.c b/cfe/cfe/ui/ui_memcmds.c
new file mode 100644
index 0000000..b48af34
--- /dev/null
+++ b/cfe/cfe/ui/ui_memcmds.c
@@ -0,0 +1,171 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Memory Map commands File: ui_memcmds.c
+ *
+ * Memory Manager user interface
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "lib_arena.h"
+
+#include "ui_command.h"
+
+#include "cfe_mem.h"
+
+#include "cfe.h"
+
+
+const static char * const cfe_arenatypes[] = {
+ "Reserved",
+ "DRAM (available)",
+ "Memory Controller (unused)",
+ "DRAM (in use by firmware)",
+ "ROM",
+ "I/O Registers",
+ "Not available",
+ "L2 Cache",
+ "LDT/PCI",
+ NULL};
+
+extern arena_t cfe_arena;
+
+
+
+int ui_init_memcmds(void);
+
+static int ui_cmd_physmap(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_heapstats(ui_cmdline_t *cmd,int argc,char *argv[]);
+
+
+int ui_init_memcmds(void)
+{
+ cmd_addcmd("show memory",
+ ui_cmd_physmap,
+ NULL,
+ "Display the system physical memory map.",
+ "show memory [-a]\n\n"
+ "This command displays the arena, or system physical memory map\n"
+ "You can use this command to determine the areas of RAM that will\n"
+ "be made available to operating systems.\n",
+ "-a;Display all entries in the map, not just the blocks\n"
+ "of available memory.");
+
+ cmd_addcmd("show heap",
+ ui_cmd_heapstats,
+ NULL,
+ "Display information about CFE's heap",
+ "show heap\n\n"
+ "This is a debugging command that can be used to determine the health\n"
+ "of CFE's internal memory manager.",
+ "");
+
+ return 0;
+}
+
+static int ui_cmd_heapstats(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int res;
+ memstats_t stats;
+
+ res = KMEMSTATS(&stats);
+
+ xprintf("\n");
+ xprintf("Total bytes: %d\n",stats.mem_totalbytes);
+ xprintf("Free bytes: %d\n",stats.mem_freebytes);
+ xprintf("Free nodes: %d\n",stats.mem_freenodes);
+ xprintf("Allocated bytes: %d\n",stats.mem_allocbytes);
+ xprintf("Allocated nodes: %d\n",stats.mem_allocnodes);
+ xprintf("Largest free node: %d\n",stats.mem_largest);
+ xprintf("Heap status: %s\n",(res == 0) ? "CONSISTENT" : "CORRUPT!");
+ xprintf("\n");
+
+ return res;
+}
+
+
+#define PHYSMAP_FLG_ALL 1
+#define PHYSMAP_FLG_AVAIL 2
+
+static int ui_cmd_physmap(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ arena_node_t *node;
+ queue_t *qb;
+ arena_t *arena = &cfe_arena;
+ int flags = 0;
+
+ if (cmd_sw_isset(cmd,"-a")) {
+ flags |= PHYSMAP_FLG_ALL;
+ }
+ else {
+ flags = PHYSMAP_FLG_AVAIL;
+ }
+
+
+ xprintf("Range Start Range End Range Size Description\n");
+ xprintf("------------ ------------ -------------- --------------------\n");
+
+ for (qb = (arena->arena_list.q_next); qb != &(arena->arena_list);
+ qb = qb->q_next) {
+ node = (arena_node_t *) qb;
+
+ if ((flags & PHYSMAP_FLG_ALL) ||
+ ((flags & PHYSMAP_FLG_AVAIL) && (node->an_type == MEMTYPE_DRAM_AVAILABLE))) {
+
+ xprintf("%012llX-%012llX (%012llX) %s\n",
+ node->an_address,
+ node->an_address+node->an_length-1,
+ node->an_length,
+ cfe_arenatypes[node->an_type]);
+ }
+
+ }
+
+ return 0;
+}
+
diff --git a/cfe/cfe/ui/ui_misccmds.c b/cfe/cfe/ui/ui_misccmds.c
new file mode 100644
index 0000000..156da6a
--- /dev/null
+++ b/cfe/cfe/ui/ui_misccmds.c
@@ -0,0 +1,178 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Miscellaneous commands File: ui_misccmds.c
+ *
+ * Some small but useful commands
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_error.h"
+#include "cfe_ioctl.h"
+#include "cfe_devfuncs.h"
+#include "ui_command.h"
+#include "cfe.h"
+
+
+static int ui_cmd_loop(ui_cmdline_t *cmd,int argc,char *argv[]);
+#ifdef _FUNCSIM_
+static int ui_cmd_exit(ui_cmdline_t *cmd,int argc,char *argv[]);
+#endif
+static int ui_cmd_console(ui_cmdline_t *cmd,int argc,char *argv[]);
+
+extern int cfe_docommands(char *buf);
+
+int ui_init_misccmds(void);
+
+int ui_init_misccmds(void)
+{
+
+ cmd_addcmd("loop",
+ ui_cmd_loop,
+ NULL,
+ "Loop a command",
+ "loop \"command\" [-count=*]\n"
+ "The 'loop' command causes the specified command or list of commands\n"
+ "to be repeated 'count' times or forever, or until a character is typed",
+ "-count=*;Specifies number of iterations|"
+ "-forever;Loops forever");
+
+#ifdef _FUNCSIM_
+ cmd_addcmd("exit",
+ ui_cmd_exit,
+ NULL,
+ "exit from the functional simulator",
+ "exit [n]\n\n"
+ "This command is useful only when running under the functional\n"
+ "simulator. It causes the simulator to exit and return to the\n"
+ "operating system. If specified, 'n' will be placed in $4 as a\n"
+ "return code.",
+ "");
+#endif
+
+ cmd_addcmd("set console",
+ ui_cmd_console,
+ NULL,
+ "Change the active console device",
+ "set console device-name\n\n"
+ "Changes the console device to the specified device name. The console\n"
+ "must be a serial-style device. Be careful not to change the console\n"
+ "to a device that is not connected!",
+ "");
+
+ return 0;
+}
+
+static int ui_cmd_loop(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int count = 10;
+ char *x;
+ int res;
+ int forever;
+
+ if (cmd_sw_value(cmd,"-count",&x)) count = atoi(x);
+
+ forever = cmd_sw_isset(cmd,"-forever");
+
+ x = cmd_getarg(cmd,0);
+ if (!x) return ui_showusage(cmd);
+
+ res = 0;
+ while (count || forever) {
+ if (console_status()) break;
+ res = ui_docommands(x);
+ if (res != 0) break;
+ count--;
+ }
+
+ return res;
+}
+
+
+#ifdef _FUNCSIM_
+static int ui_cmd_exit(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int val = 0;
+ char *x;
+
+ x = cmd_getarg(cmd,0);
+ if (x) val = atoi(x);
+
+ __asm __volatile ("move $4,%0 ; li $2,1 ; syscall 0xca" : "=r"(val));
+
+ return -1;
+}
+#endif
+
+
+static int ui_cmd_console(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int res;
+ char *dev;
+
+ dev = cmd_getarg(cmd,0);
+ if (!dev) return -1; /* XXX usage */
+
+ res = cfe_getdevinfo(dev);
+ if (res < 0) {
+ xprintf("Device '%s' is not valid\n",dev);
+ return CFE_ERR_DEVNOTFOUND;
+ }
+
+ if ((res & CFE_DEV_MASK) != CFE_DEV_SERIAL) {
+ xprintf("Device '%s' is not the appropriate type to be a console\n",
+ dev);
+ return CFE_ERR_WRONGDEVTYPE;
+ }
+
+ cfe_set_console(dev);
+
+ return 0;
+}
diff --git a/cfe/cfe/ui/ui_netcmds.c b/cfe/cfe/ui/ui_netcmds.c
new file mode 100644
index 0000000..891e127
--- /dev/null
+++ b/cfe/cfe/ui/ui_netcmds.c
@@ -0,0 +1,710 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Network commands File: ui_netcmds.c
+ *
+ * Network user interface
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_devfuncs.h"
+#include "cfe_timer.h"
+#include "cfe_ioctl.h"
+
+#include "cfe_error.h"
+
+#include "env_subr.h"
+#include "ui_command.h"
+#include "cfe.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+
+#include "net_api.h"
+
+#include "cfe_fileops.h"
+
+#include "bsp_config.h"
+
+#define ip_addriszero(a) (((a)[0]|(a)[1]|(a)[2]|(a)[3]) == 0)
+#define isdigit(d) (((d) >= '0') && ((d) <= '9'))
+
+int ui_init_netcmds(void);
+
+#if CFG_NETWORK
+static int ui_cmd_ifconfig(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_arp(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_ping(ui_cmdline_t *cmd,int argc,char *argv[]);
+#if CFG_TCP
+extern int ui_init_tcpcmds(void);
+#endif
+#endif
+
+typedef struct netparam_s {
+ const char *str;
+ int num;
+} netparam_t;
+
+const static netparam_t loopbacktypes[] = {
+ {"off",ETHER_LOOPBACK_OFF},
+ {"internal",ETHER_LOOPBACK_INT},
+ {"external",ETHER_LOOPBACK_EXT},
+ {0,NULL}};
+
+const static netparam_t speedtypes[] = {
+ {"auto",ETHER_SPEED_AUTO},
+ {"10hdx",ETHER_SPEED_10HDX},
+ {"10fdx",ETHER_SPEED_10FDX},
+ {"100hdx",ETHER_SPEED_100HDX},
+ {"100fdx",ETHER_SPEED_100FDX},
+ {"1000hdx",ETHER_SPEED_1000HDX},
+ {"1000fdx",ETHER_SPEED_1000FDX},
+ {0,NULL}};
+
+
+int ui_init_netcmds(void)
+{
+#if CFG_NETWORK
+ cmd_addcmd("ifconfig",
+ ui_cmd_ifconfig,
+ NULL,
+ "Configure the Ethernet interface",
+ "ifconfig device [options..]\n\n"
+ "Activates and configures the specified Ethernet interface and sets its\n"
+ "IP address, netmask, and other parameters. The -auto switch can be used\n"
+ "to set this information via DHCP.",
+ "-auto;Configure interface automatically via DHCP|"
+ "-off;Deactivate the specified interface|"
+ "-addr=*;Specifies the IP address of the interface|"
+ "-mask=*;Specifies the subnet mask for the interface|"
+ "-gw=*;Specifies the gateway address for the interface|"
+ "-dns=*;Specifies the name server address for the interface|"
+ "-domain=*;Specifies the default domain for name service queries|"
+ "-speed=*;Sets the interface speed (auto,10fdx,10hdx,\n100fdx,\n"
+ "100hdx,1000fdx,1000hdx)|"
+ "-loopback=*;Sets the loopback mode (off,internal,external) "
+ "External\nloopback causes the phy to be placed in loopback mode|"
+ "-hwaddr=*;Sets the hardware address (overrides environment)");
+
+ cmd_addcmd("arp",
+ ui_cmd_arp,
+ NULL,
+ "Display or modify the ARP Table",
+ "arp [-d] [ip-address] [dest-address]\n\n"
+ "Without any parameters, the arp command will display the contents of the\n"
+ "arp table. With two parameters, arp can be used to add permanent arp\n"
+ "entries to the table (permanent arp entries do not time out)",
+ "-d;Delete the specified ARP entry. If specified, ip-address\n"
+ "may be * to delete all entries.");
+
+ cmd_addcmd("ping",
+ ui_cmd_ping,
+ NULL,
+ "Ping a remote IP host.",
+ "ping [-t] remote-host\n\n"
+ "This command sends an ICMP ECHO message to a remote host and waits for \n"
+ "a reply. The network interface must be configured and operational for\n"
+ "this command to work. If the interface is configured for loopback mode\n"
+ "the packet will be sent through the network interface, so this command\n"
+ "can be used for a simple network test.",
+ "-t;Ping forever, or until the ENTER key is struck|"
+ "-x;Exit immediately on first error (use with -f or -t)|"
+ "-f;Flood ping (use carefully!) - ping as fast as possible|"
+ "-s=*;Specify the number of ICMP data bytes|"
+ "-c=*;Specify number of packets to echo|"
+ "-A;don't abort even if key is pressed|"
+ "-E;Require all packets sent to be returned, for successful return status");
+
+#if CFG_TCP
+ /* Foxconn add start by Cliff Wang, 03/23/2010 */
+ //ui_init_tcpcmds();
+ /* Foxconn add end by Cliff Wang, 03/23/2010 */
+#endif
+
+
+#endif
+
+ return 0;
+}
+
+
+#if CFG_NETWORK
+static int parsexdigit(char str)
+{
+ int digit;
+
+ if ((str >= '0') && (str <= '9')) digit = str - '0';
+ else if ((str >= 'a') && (str <= 'f')) digit = str - 'a' + 10;
+ else if ((str >= 'A') && (str <= 'F')) digit = str - 'A' + 10;
+ else return -1;
+
+ return digit;
+}
+
+
+static int parsehwaddr(char *str,uint8_t *hwaddr)
+{
+ int digit1,digit2;
+ int idx = 6;
+
+ while (*str && (idx > 0)) {
+ digit1 = parsexdigit(*str);
+ if (digit1 < 0) return -1;
+ str++;
+ if (!*str) return -1;
+
+ if ((*str == ':') || (*str == '-')) {
+ digit2 = digit1;
+ digit1 = 0;
+ }
+ else {
+ digit2 = parsexdigit(*str);
+ if (digit2 < 0) return -1;
+ str++;
+ }
+
+ *hwaddr++ = (digit1 << 4) | digit2;
+ idx--;
+
+ if (*str == '-') str++;
+ if (*str == ':') str++;
+ }
+ return 0;
+}
+
+
+
+static int ui_ifdown(void)
+{
+ char *devname;
+
+ devname = (char *) net_getparam(NET_DEVNAME);
+ if (devname) {
+ xprintf("Device %s has been deactivated.\n",devname);
+ net_uninit();
+ net_setnetvars();
+ }
+
+ return 0;
+}
+
+static void ui_showifconfig(void)
+{
+ char *devname;
+ uint8_t *addr;
+
+ devname = (char *) net_getparam(NET_DEVNAME);
+ if (devname == NULL) {
+ xprintf("Network interface has not been configured\n");
+ return;
+ }
+
+ xprintf("Device %s: ",devname);
+
+ addr = net_getparam(NET_HWADDR);
+ if (addr) xprintf(" hwaddr %a",addr);
+
+ addr = net_getparam(NET_IPADDR);
+ if (addr) {
+ if (ip_addriszero(addr)) xprintf(", ipaddr not set");
+ else xprintf(", ipaddr %I",addr);
+ }
+
+ addr = net_getparam(NET_NETMASK);
+ if (addr) {
+ if (ip_addriszero(addr)) xprintf(", mask not set");
+ else xprintf(", mask %I",addr);
+ }
+
+ xprintf("\n");
+ xprintf(" ");
+
+ addr = net_getparam(NET_GATEWAY);
+ if (addr) {
+ if (ip_addriszero(addr)) xprintf("gateway not set");
+ else xprintf("gateway %I",addr);
+ }
+
+ addr = net_getparam(NET_NAMESERVER);
+ if (addr) {
+ if (ip_addriszero(addr)) xprintf(", nameserver not set");
+ else xprintf(", nameserver %I",addr);
+ }
+
+ addr = net_getparam(NET_DOMAIN);
+ if (addr) {
+ xprintf(", domain %s",addr);
+ }
+
+ xprintf("\n");
+}
+
+/* Foxconn add start by Cliff Wang, 03/23/2010 */
+#if 0
+static int ui_ifconfig_auto(ui_cmdline_t *cmd,char *devname)
+{
+ int err;
+ dhcpreply_t *reply = NULL;
+ char *x;
+ uint8_t hwaddr[6];
+
+ net_uninit();
+
+ err = net_init(devname);
+ if (err < 0) {
+ xprintf("Could not activate device %s: %s\n",
+ devname,cfe_errortext(err));
+ return err;
+ }
+
+ if (cmd_sw_value(cmd,"-hwaddr",&x)) {
+ if (parsehwaddr(x,hwaddr) != 0) {
+ xprintf("Invalid hardware address: %s\n",x);
+ net_uninit();
+ return CFE_ERR_INV_PARAM;
+ }
+ else {
+ net_setparam(NET_HWADDR,hwaddr);
+ }
+ }
+
+ err = dhcp_bootrequest(&reply);
+
+ if (err < 0) {
+ xprintf("DHCP registration failed on device %s\n",devname);
+ net_uninit();
+ return CFE_ERR_NETDOWN;
+ }
+
+ net_setparam(NET_IPADDR,reply->dr_ipaddr);
+ net_setparam(NET_NETMASK,reply->dr_netmask);
+ net_setparam(NET_GATEWAY,reply->dr_gateway);
+ net_setparam(NET_NAMESERVER,reply->dr_nameserver);
+ net_setparam(NET_DOMAIN,reply->dr_domainname);
+
+ dhcp_set_envvars(reply);
+
+ if (reply) dhcp_free_reply(reply);
+
+ ui_showifconfig();
+ net_setnetvars();
+ return 0;
+}
+#endif
+/* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+static int ui_ifconfig_getsw(ui_cmdline_t *cmd,char *swname,char *descr,uint8_t *addr)
+{
+ char *x;
+
+ x = NULL;
+
+ if (cmd_sw_value(cmd,swname,&x) == 0) return 0;
+
+ if ((x == NULL) || (parseipaddr(x,addr) < 0)) {
+ xprintf("Invalid %s: %s\n",descr,x ? x : "(none)");
+ return -1;
+ }
+
+ return 1;
+}
+
+static int ui_ifconfig_lookup(char *name,char *val,const netparam_t *list)
+{
+ const netparam_t *p = list;
+
+ while (p->str) {
+ if (strcmp(p->str,val) == 0) return p->num;
+ p++;
+ }
+
+ xprintf("Invalid parameter for %s: Valid options are: ");
+
+ p = list;
+ while (p->str) {
+ xprintf("%s ",p->str);
+ p++;
+ }
+
+ xprintf("\n");
+ return -1;
+}
+
+
+#define FLG_IPADDR 1
+#define FLG_NETMASK 2
+#define FLG_GATEWAY 4
+#define FLG_NAMESERVER 8
+#define FLG_DOMAIN 16
+#define FLG_LOOPBACK 32
+#define FLG_SPEED 64
+#define FLG_HWADDR 128
+
+static int ui_cmd_ifconfig(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *devname;
+ int flags = 0;
+ uint8_t ipaddr[IP_ADDR_LEN];
+ uint8_t netmask[IP_ADDR_LEN];
+ uint8_t gateway[IP_ADDR_LEN];
+ uint8_t nameserver[IP_ADDR_LEN];
+ uint8_t hwaddr[6];
+ int speed = ETHER_SPEED_AUTO;
+ int loopback = ETHER_LOOPBACK_OFF;
+ char *domain = NULL;
+ int res;
+ char *x;
+
+ if (argc < 1) {
+ ui_showifconfig();
+ return 0;
+ }
+
+ devname = cmd_getarg(cmd,0);
+
+ if (cmd_sw_isset(cmd,"-off")) {
+ return ui_ifdown();
+ }
+
+ /* Foxconn add start by Cliff Wang, 03/23/2010 */
+#if 0
+ if (cmd_sw_isset(cmd,"-auto")) {
+ return ui_ifconfig_auto(cmd,devname);
+ }
+#endif
+ /* Foxconn add end by Cliff Wang, 03/23/2010 */
+
+ res = ui_ifconfig_getsw(cmd,"-addr","interface IP address",ipaddr);
+ if (res < 0) return CFE_ERR_INV_PARAM;
+ if (res > 0) {
+ flags |= FLG_IPADDR;
+ }
+
+ res = ui_ifconfig_getsw(cmd,"-mask","netmask",netmask);
+ if (res < 0) return CFE_ERR_INV_PARAM;
+ if (res > 0) {
+ flags |= FLG_NETMASK;
+ }
+
+ res = ui_ifconfig_getsw(cmd,"-gw","gateway IP address",gateway);
+ if (res < 0) return CFE_ERR_INV_PARAM;
+ if (res > 0) {
+ flags |= FLG_GATEWAY;
+ }
+
+ res = ui_ifconfig_getsw(cmd,"-dns","name server IP address",nameserver);
+ if (res < 0) return CFE_ERR_INV_PARAM;
+ if (res > 0) {
+ flags |= FLG_NAMESERVER;
+ }
+
+ if (cmd_sw_value(cmd,"-domain",&domain)) {
+ if (domain) flags |= FLG_DOMAIN;
+ }
+
+ if (cmd_sw_value(cmd,"-speed",&x)) {
+ speed = ui_ifconfig_lookup("-speed",x,speedtypes);
+ if (speed >= 0) flags |= FLG_SPEED;
+ else return CFE_ERR_INV_PARAM;
+ }
+
+ if (cmd_sw_value(cmd,"-loopback",&x)) {
+ loopback = ui_ifconfig_lookup("-loopback",x,loopbacktypes);
+ if (loopback >= 0) flags |= FLG_LOOPBACK;
+ else return CFE_ERR_INV_PARAM;
+ }
+
+ if (cmd_sw_value(cmd,"-hwaddr",&x)) {
+ if (parsehwaddr(x,hwaddr) != 0) {
+ xprintf("Invalid hardware address: %s\n",x);
+ return CFE_ERR_INV_PARAM;
+ }
+ else {
+ flags |= FLG_HWADDR;
+ }
+ }
+
+ /*
+ * If the network is running and the device name is
+ * different, uninit the net first.
+ */
+
+ x = (char *) net_getparam(NET_DEVNAME);
+
+ if ((x != NULL) && (strcmp(x,devname) != 0)) {
+ net_uninit();
+ }
+
+ /*
+ * Okay, initialize the network if it is not already on. If it
+ * is OFF, the "net_devname" parameter will be NULL.
+ */
+
+ if (x == NULL) {
+ res = net_init(devname); /* turn interface on */
+ if (res < 0) {
+ ui_showerror(res,"Could not activate network interface '%s'",devname);
+ return res;
+ }
+ }
+
+ /*
+ * Set the parameters
+ */
+
+ if (flags & FLG_HWADDR) net_setparam(NET_HWADDR,hwaddr);
+ if (flags & FLG_IPADDR) net_setparam(NET_IPADDR,ipaddr);
+ if (flags & FLG_NETMASK) net_setparam(NET_NETMASK,netmask);
+ if (flags & FLG_GATEWAY) net_setparam(NET_GATEWAY,gateway);
+ if (flags & FLG_NAMESERVER) net_setparam(NET_NAMESERVER,nameserver);
+ /* Foxconn add start by Cliff Wang, 03/23/2010 */
+ if (flags & FLG_DOMAIN) net_setparam(NET_DOMAIN,(uint8_t *) domain);
+ /* Foxconn add end by Cliff Wang, 03/23/2010 */
+ if (flags & FLG_SPEED) net_setparam(NET_SPEED,(uint8_t *) &speed);
+ if (flags & FLG_LOOPBACK) net_setparam(NET_LOOPBACK,(uint8_t *) &loopback);
+
+ ui_showifconfig();
+ net_setnetvars();
+
+ return 0;
+}
+
+
+static int ui_cmd_arp(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int idx;
+ uint8_t ipaddr[IP_ADDR_LEN];
+ uint8_t hwaddr[ENET_ADDR_LEN];
+ char *x;
+ int once = 0;
+
+ if (cmd_sw_isset(cmd,"-d")) {
+ if ((x = cmd_getarg(cmd,0)) == NULL) {
+ return ui_showusage(cmd);
+ }
+
+ if (strcmp(x,"*") == 0) {
+ while (arp_enumerate(0,ipaddr,hwaddr) >= 0) {
+ arp_delete(ipaddr);
+ }
+ }
+ else {
+ if (parseipaddr(x,ipaddr) < 0) {
+ xprintf("Invalid IP address: %s\n",x);
+ return CFE_ERR_INV_PARAM;
+ }
+ arp_delete(ipaddr);
+ }
+ return 0;
+ }
+
+ /*
+ * Get the IP address. If NULL, display the table.
+ */
+
+ x = cmd_getarg(cmd,0);
+ if (x == NULL) {
+ idx = 0;
+ while (arp_enumerate(idx,ipaddr,hwaddr) >= 0) {
+ if (once == 0) {
+ xprintf("Hardware Address IP Address\n");
+ xprintf("----------------- ---------------\n");
+ once = 1;
+ }
+ xprintf("%a %I\n",hwaddr,ipaddr);
+ idx++;
+ }
+ if (idx == 0) xprintf("No ARP entries.\n");
+ return 0;
+ }
+
+ if (parseipaddr(x,ipaddr) < 0) {
+ xprintf("Invalid IP address: %s\n",x);
+ return CFE_ERR_INV_PARAM;
+ }
+
+ /*
+ * Get the hardware address.
+ */
+
+ x = cmd_getarg(cmd,1);
+ if (x == NULL) {
+ return ui_showusage(cmd);
+ }
+
+ if (parsehwaddr(x,hwaddr) < 0) {
+ xprintf("Invalid hardware address: %s\n",x);
+ return CFE_ERR_INV_PARAM;
+ }
+
+ arp_add(ipaddr,hwaddr);
+
+ return 0;
+}
+
+#define IP_HDR_LENGTH 20
+#define ICMP_HDR_LENGTH 8
+#define PING_HDR_LENGTH (IP_HDR_LENGTH+ICMP_HDR_LENGTH)
+#define MAX_PKT_LENGTH 1500
+
+static int ui_cmd_ping(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *host;
+ uint8_t hostaddr[IP_ADDR_LEN];
+ int res;
+ int seq = 0;
+ int forever = 0;
+ int count = 1;
+ int ttlcount = 1;
+ int countreturned = 0;
+ int size = 56;
+ int flood = 0;
+ int retval = 0;
+ int exitonerror = 0;
+ int needexact = 0;
+ int noabort = 0;
+ char *x;
+
+ host = cmd_getarg(cmd,0);
+ if (!host) return -1;
+
+ if (cmd_sw_isset(cmd,"-t")) {
+ forever = 1;
+ }
+
+ /* Per traditional Unix usage, the size argument to ping is
+ the number of ICMP data bytes. The frame on the wire will also
+ include the ethernet, IP and ICMP headers (14, 20, and
+ 8 bytes respectively) and ethernet trailer (CRC, 4 bytes). */
+ if (cmd_sw_value(cmd,"-s",&x)) {
+ size = atoi(x);
+ if (size < 0)
+ size = 0;
+ if (size > MAX_PKT_LENGTH - PING_HDR_LENGTH)
+ size = MAX_PKT_LENGTH - PING_HDR_LENGTH;
+ }
+
+ if (cmd_sw_isset(cmd,"-f")) {
+ flood = 1;
+ forever = 1;
+ }
+
+ if (cmd_sw_isset(cmd,"-x")) {
+ exitonerror = 1;
+ }
+
+ if (cmd_sw_value(cmd,"-c",&x)) {
+ count = atoi(x);
+ ttlcount = count;
+ forever = 0;
+ }
+
+ if (cmd_sw_isset(cmd,"-A")) {
+ noabort = 1;
+ }
+
+ if (cmd_sw_isset(cmd,"-E")) {
+ needexact = 1;
+ }
+
+ if (isdigit(*host)) {
+ if (parseipaddr(host,hostaddr) < 0) {
+ xprintf("Invalid IP address: %s\n",host);
+ return -1;
+ }
+ }
+ else {
+ res = dns_lookup(host,hostaddr);
+ if (res < 0) {
+ return ui_showerror(res,"Could not resolve IP address of host %s",host);
+ }
+ }
+
+ if (forever) xprintf("Press ENTER to stop pinging\n");
+
+ do {
+ res = icmp_ping(hostaddr,seq,size);
+
+ if (res < 0) {
+ xprintf("Could not transmit echo request\n");
+ retval = CFE_ERR_IOERR;
+ break;
+ }
+ else if (res == 0) {
+ xprintf("%s (%I) is not responding (seq=%d)\n",host,hostaddr,seq);
+ retval = CFE_ERR_TIMEOUT;
+ if (exitonerror) break;
+ }
+ else {
+ countreturned++;
+ if (!flood || ((seq % 10000) == 0)) {
+ if (forever || (ttlcount > 1)) {
+ xprintf("%s (%I) is alive (seq=%d)\n",host,hostaddr,seq);
+ }
+ else xprintf("%s (%I) is alive\n",host,hostaddr);
+ }
+ }
+
+ if ((forever || (count > 1)) && !flood) {
+ if (res > 0) cfe_sleep(CFE_HZ);
+ }
+
+ seq++;
+ count--;
+
+ } while ((forever || (count > 0)) && (noabort || !console_status()));
+
+ xprintf("%s (%I): %d packets sent, %d received\n",host,hostaddr,
+ ttlcount-count,countreturned);
+ return (needexact ? (countreturned != ttlcount) : (countreturned == 0));
+}
+
+#endif
diff --git a/cfe/cfe/ui/ui_pcicmds.c b/cfe/cfe/ui/ui_pcicmds.c
new file mode 100644
index 0000000..8875f8e
--- /dev/null
+++ b/cfe/cfe/ui/ui_pcicmds.c
@@ -0,0 +1,282 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * PCI Commands File: ui_pcicmds.c
+ *
+ * PCI user interface routines
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "env_subr.h"
+#include "ui_command.h"
+#include "cfe.h"
+
+#include "pcivar.h"
+#include "pcireg.h"
+
+#include "bsp_config.h"
+
+int ui_init_pcicmds(void);
+
+#if CFG_PCI
+static int pci_print_summary(pcitag_t tag)
+{
+ pcireg_t id, class;
+ char devinfo[256];
+
+ class = pci_conf_read(tag, PCI_CLASS_REG);
+ id = pci_conf_read(tag, PCI_ID_REG);
+
+ pci_devinfo(id, class, 1, devinfo);
+ pci_tagprintf (tag, "%s\n", devinfo);
+
+ return 0;
+}
+
+static int pci_print_concise(pcitag_t tag)
+{
+ pci_tagprintf (tag, "\n");
+ pci_conf_print(tag);
+
+ return 0;
+}
+
+static int ui_cmd_pci(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *argp;
+
+ if (cmd_sw_isset(cmd,"-init")) {
+ pci_configure(PCI_FLG_LDT_PREFETCH | PCI_FLG_NORMAL);
+ return 0;
+ }
+
+ argp = cmd_getarg(cmd,0);
+
+ if (argp == NULL) {
+ if (cmd_sw_isset(cmd,"-v")) {
+ pci_foreachdev(pci_print_concise);
+ }
+ else {
+ pci_foreachdev(pci_print_summary);
+ }
+ }
+ else {
+ /* parse the triplet */
+ int bus, dev, func;
+ pcitag_t tag;
+ char *p;
+
+ bus = dev = func = 0;
+ p = argp;
+
+ while (*p >= '0' && *p <= '9') {
+ bus = bus*10 + (*p - '0');
+ p++;
+ }
+ if (*p != '/')
+ goto fail;
+ p++;
+ while (*p >= '0' && *p <= '9') {
+ dev = dev*10 + (*p - '0');
+ p++;
+ }
+ if (*p != '/')
+ goto fail;
+ p++;
+ while (*p >= '0' && *p <= '9') {
+ func = func*10 + (*p - '0');
+ p++;
+ }
+ if (*p != '\000')
+ goto fail;
+
+ tag = pci_make_tag(bus,dev,func);
+
+ pci_print_concise(tag);
+ }
+
+ return 0;
+
+fail:
+ printf("invalid PCI triplet %s\n", argp);
+ return -1;
+}
+
+
+static uint64_t parse_hex(const char *num)
+{
+ uint64_t x = 0;
+ unsigned int digit;
+
+ if ((*num == '0') && (*(num+1) == 'x')) num += 2;
+
+ while (*num) {
+ if ((*num >= '0') && (*num <= '9')) {
+ digit = *num - '0';
+ }
+ else if ((*num >= 'A') && (*num <= 'F')) {
+ digit = 10 + *num - 'A';
+ }
+ else if ((*num >= 'a') && (*num <= 'f')) {
+ digit = 10 + *num - 'a';
+ }
+ else {
+ break;
+ }
+ x *= 16;
+ x += digit;
+ num++;
+ }
+
+ return x;
+}
+
+static int ui_cmd_map_pci(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ unsigned long offset, size;
+ uint64_t paddr;
+ int l2ca, endian;
+ int enable;
+ int result;
+
+ enable = !cmd_sw_isset(cmd, "-off");
+ if (enable) {
+ offset = parse_hex(cmd_getarg(cmd, 0));
+ size = parse_hex(cmd_getarg(cmd, 1));
+ paddr = parse_hex(cmd_getarg(cmd, 2));
+ l2ca = cmd_sw_isset(cmd,"-l2ca");
+ endian = cmd_sw_isset(cmd, "-matchbits");
+ result = pci_map_window(paddr, offset, size, l2ca, endian);
+ }
+ else {
+ offset = parse_hex(cmd_getarg(cmd, 0));
+ size = parse_hex(cmd_getarg(cmd, 1));
+ result = pci_unmap_window(offset, size);
+ }
+
+ return result;
+}
+#endif
+
+#ifdef CFG_VGACONSOLE
+
+extern int vga_biosinit(void);
+extern int vga_probe(void);
+extern void vgaraw_dump(char *tail);
+
+static int ui_cmd_vgainit(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int res;
+
+ if (vga_probe() == 0) {
+ res = vga_biosinit();
+ xprintf("vgabios_init returns %d\n",res);
+ }
+ else
+ xprintf("vga_probe found no suitable adapter\n");
+
+ return 0;
+}
+
+static int ui_cmd_vgadump(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *x;
+
+ x = cmd_getarg(cmd,0);
+ if (x == NULL) x = "";
+ vgaraw_dump(x);
+
+ return 0;
+}
+#endif /* CFG_VGACONSOLE */
+
+
+int ui_init_pcicmds(void)
+{
+
+#if CFG_PCI
+ cmd_addcmd("show pci",
+ ui_cmd_pci,
+ NULL,
+ "Display information about PCI buses and devices",
+ "show pci [-v] [bus/dev/func]\n\n"
+ "Displays information about PCI and LDT buses and devices in the\n"
+ "system. If you specify a bus/dev/func triplet, only that device\n"
+ " will be displayed.",
+ "-v;Display verbose information|"
+ "-init;Reinitialize and rescan the PCI bus");
+ cmd_addcmd("map pci",
+ ui_cmd_map_pci,
+ NULL,
+ "Define a BAR0 window available to PCI devices",
+ "map pci offset size paddr [-off] [-l2ca] [-matchbits]\n\n"
+ "Map the region of size bytes starting at paddr to appear\n"
+ "at offset relative to BAR0\n",
+ "-off;Remove the region|"
+ "-l2ca;Make L2 cachable|"
+ "-matchbits;Use match bits policy");
+
+#ifdef CFG_VGACONSOLE
+ cmd_addcmd("vga init",
+ ui_cmd_vgainit,
+ NULL,
+ "Initialize the VGA adapter.",
+ "vgainit",
+ "");
+ cmd_addcmd("vga dumpbios",
+ ui_cmd_vgadump,
+ NULL,
+ "Dump the VGA BIOS to the console",
+ "vga dumpbios",
+ "");
+#endif /* CFG_VGACONSOLE */
+#endif
+ return 0;
+}
diff --git a/cfe/cfe/ui/ui_tcpcmds.c b/cfe/cfe/ui/ui_tcpcmds.c
new file mode 100644
index 0000000..e092021
--- /dev/null
+++ b/cfe/cfe/ui/ui_tcpcmds.c
@@ -0,0 +1,828 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * TCP protocol commands File: ui_tcpcmds.c
+ *
+ * This file contains commands that make use of the TCP protocol
+ * in CFE, assuming it's configured.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_timer.h"
+
+#include "cfe_error.h"
+#include "cfe_console.h"
+
+#include "ui_command.h"
+#include "cfe.h"
+
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+
+#include "bsp_config.h"
+
+#if CFG_TCP
+#include "net_ebuf.h"
+#include "net_api.h"
+#endif
+
+
+/* *********************************************************************
+ * Configuration
+ ********************************************************************* */
+
+/* *********************************************************************
+ * prototypes
+ ********************************************************************* */
+
+#if CFG_TCP
+
+int ui_init_tcpcmds(void);
+
+static int ui_cmd_rlogin(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_connect(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_listen(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_tcpconstest(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_ttcp(ui_cmdline_t *cmd,int argc,char *argv[]);
+#define isdigit(d) (((d) >= '0') && ((d) <= '9'))
+
+
+/* *********************************************************************
+ * ui_init_tcpcmds()
+ *
+ * Add TCP-specific commands to the command table
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+
+int ui_init_tcpcmds(void)
+{
+
+ cmd_addcmd("rlogin",
+ ui_cmd_rlogin,
+ NULL,
+ "mini rlogin client.",
+ "rlogin hostname [username]\n\n"
+ "Connects to a remote system using the RLOGIN protocol. The remote"
+ "system must have appropriate permissions in place (usually via the"
+ "file '.rhosts') for CFE to connect. To terminate the session, type"
+ "a tilde (~) character followed by a period (.)",
+ "");
+
+ cmd_addcmd("tcp connect",
+ ui_cmd_connect,
+ NULL,
+ "TCP connection test.",
+ "tcp connect hostname [portnum]",
+ "-q;sink output, don't display on terminal|"
+ "-d;Send junk data to discard|"
+ "-nodelay;set nodelay option on socket|"
+ "-srcport=*;Specify the source port");
+
+ cmd_addcmd("tcp listen",
+ ui_cmd_listen,
+ NULL,
+ "port listener.",
+ "tcp listen portnum",
+ "-q;sink output, don't display on terminal|"
+ "-d;Send junk data to discard|"
+ "-nodelay;set nodelay option on socket");
+
+
+ cmd_addcmd("tcp constest",
+ ui_cmd_tcpconstest,
+ NULL,
+ "tcp console test.",
+ "tcp constest device",
+ "");
+
+ cmd_addcmd("ttcp",
+ ui_cmd_ttcp,
+ NULL,
+ "TCP test command.",
+ "ttcp -t [-options] host\n"
+ "ttcp -r [-options]\n\n",
+ "-t;Source a pattern to the network|"
+ "-r;Sink (discard) data from the network|"
+ "-D;Don't buffer TCP writes (TCP_NODELAY)|"
+ "-n=*;Number of buffers to send (-t only) (default 2048)|"
+ "-l=*;Size of buffer to send/receive (default 2048)|"
+ "-p=*;Port number to use (default 5001)");
+
+ return 0;
+}
+
+
+
+
+
+static unsigned long rand(void)
+{
+ static unsigned long seed = 1;
+ long x, hi, lo, t;
+
+ x = seed;
+ hi = x / 127773;
+ lo = x % 127773;
+ t = 16807 * lo - 2836 * hi;
+ if (t <= 0) t += 0x7fffffff;
+ seed = t;
+ return t;
+}
+
+
+static int ui_cmd_rlogin(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int s;
+ uint8_t hostaddr[IP_ADDR_LEN];
+ char *host;
+ int res;
+ int connflag;
+ int rxdata;
+ int sport;
+ uint8_t data[100];
+ int tilde;
+ char *username;
+ uint8_t *p;
+
+ /*
+ * Process args
+ */
+
+ host = cmd_getarg(cmd,0);
+ if (!host) return ui_showusage(cmd);
+
+ username = cmd_getarg(cmd,1);
+ if (!username) username = "";
+
+ /*
+ * Look up remote host
+ */
+
+ if (isdigit(*host)) {
+ if (parseipaddr(host,hostaddr) < 0) {
+ xprintf("Invalid IP address: %s\n",host);
+ return -1;
+ }
+ }
+ else {
+ res = dns_lookup(host,hostaddr);
+ if (res < 0) {
+ return ui_showerror(res,"Could not resolve IP address of host %s",host);
+ }
+ }
+
+ /*
+ * Create TCP socket and bind to a port number less than 1023
+ * See RFC1282 for more info about this
+ */
+
+ s = tcp_socket();
+
+ if (s < 0) {
+ return ui_showerror(s,"Could not create TCP socket");
+ }
+
+ res = 0;
+ tilde = 0;
+ for (sport = 1023; sport > 513; sport--) {
+ res = tcp_bind(s,sport);
+ if (res == 0) break;
+ }
+
+ if (sport == 513) {
+ ui_showerror(res,"No ports available for RLOGIN");
+ return res;
+ }
+
+ /*
+ * Establish a connection. Our sockets default to nonblocking
+ * so we want to switch to blocking temporarily to
+ * let the tcp_connect routine do this by itself.
+ */
+
+ tcp_setflags(s,0);
+ res = tcp_connect(s,hostaddr,513);
+ if (res < 0) {
+ ui_showerror(res,"Could not connect to host %I",hostaddr);
+ tcp_close(s);
+ return res;
+ }
+
+
+ /*
+ * Construct the initial RLOGIN sequence to include
+ * our user name and terminal type
+ */
+
+ p = data;
+ *p++ = '\0';
+ p += sprintf(p,"%s",username) + 1;
+ p += sprintf(p,"%s",username) + 1;
+ p += sprintf(p,"vt100/38400") + 1;
+
+ tcp_send(s,data,p-&data[0]);
+
+ res = tcp_recv(s,data,1); /* receive result code */
+ if (res <= 0) {
+ goto remdisc;
+ }
+
+ /*
+ * Switch back to nonblocking I/O for the loop
+ */
+
+ tcp_setflags(s,TCPFLG_NBIO);
+
+ /*
+ * Begin processing loop
+ */
+
+ connflag = TRUE;
+ for (;;) {
+
+ /*
+ * Test connection status
+ */
+
+ tcp_status(s,&connflag,&rxdata,NULL);
+ if (connflag != TCPSTATUS_CONNECTED) {
+ goto remdisc;
+ }
+
+ /*
+ * Process received data
+ */
+
+ if (rxdata != 0) {
+ res = tcp_recv(s,data,sizeof(data));
+ if (res > 0) {
+ console_write(data,res);
+ }
+ if (res < 0) {
+ ui_showerror(res,"TCP read error");
+ break;
+ }
+ }
+
+ /*
+ * Process transmitted data
+ */
+
+ if (console_status()) {
+ console_read(data,1);
+ if (tilde == 1) {
+ if (data[0] == '.') break;
+ tcp_send(s,data,1);
+ }
+ else {
+ if (data[0] == '~') tilde = 1;
+ else tcp_send(s,data,1);
+ }
+ }
+
+ /*
+ * Give the background a chance
+ */
+
+ POLL();
+ }
+
+ printf("Disconnecting...");
+ tcp_close(s);
+ printf("done.\n");
+ return 0;
+
+remdisc:
+ printf("Remote host is no longer connected.\n");
+ tcp_close(s);
+ return 0;
+}
+
+
+
+static int ui_cmd_connect(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int s;
+ uint8_t hostaddr[IP_ADDR_LEN];
+ char *host;
+ char *port;
+ int res;
+ int connflag;
+ int rxdata;
+ uint8_t data[100];
+ int quiet;
+ int discard;
+ int total = 0;
+ int total2 = 0;
+ char b = 0;
+ cfe_timer_t t;
+ char *bigbuf;
+ int nodelay;
+ char *sport = NULL;
+
+ bigbuf = KMALLOC(4096,0);
+ for (res = 0; res < 4096; res++) bigbuf[res] = 'A'+(res%26);
+
+ quiet = cmd_sw_isset(cmd,"-q");
+ discard = cmd_sw_isset(cmd,"-d");
+ nodelay = cmd_sw_isset(cmd,"-nodelay");
+
+ host = cmd_getarg(cmd,0);
+ if (!host) return -1;
+
+ port = cmd_getarg(cmd,1);
+ if (!port) port = "23";
+
+ if (strcmp(port,"discard") == 0) port = "9";
+ else if (strcmp(port,"chargen") == 0) port = "19";
+ else if (strcmp(port,"echo") == 0) port = "7";
+
+ if (isdigit(*host)) {
+ if (parseipaddr(host,hostaddr) < 0) {
+ xprintf("Invalid IP address: %s\n",host);
+ return -1;
+ }
+ }
+ else {
+ res = dns_lookup(host,hostaddr);
+ if (res < 0) {
+ return ui_showerror(res,"Could not resolve IP address of host %s",host);
+ }
+ }
+
+
+ s = tcp_socket();
+
+ if (s < 0) {
+ return ui_showerror(s,"Could not create TCP socket");
+ }
+
+ if (cmd_sw_value(cmd,"-srcport",&sport)) {
+ res = tcp_bind(s,atoi(sport));
+ if (res < 0) {
+ ui_showerror(res,"Could not bind to port %s",sport);
+ tcp_close(s);
+ return res;
+ }
+ }
+
+ res = tcp_connect(s,hostaddr,atoi(port));
+ if (res < 0) {
+ ui_showerror(res,"Could not connect to host %I",hostaddr);
+ tcp_close(s);
+ return res;
+ }
+
+ TIMER_SET(t,CFE_HZ*30);
+ connflag = 0;
+ while (!TIMER_EXPIRED(t)) {
+ POLL();
+ tcp_status(s,&connflag,NULL,NULL);
+ if (connflag == TCPSTATUS_CONNECTING) continue;
+ break;
+ }
+
+ if (connflag != TCPSTATUS_CONNECTED) {
+ printf("Could not connect to remote host\n");
+ tcp_close(s);
+ return -1;
+ }
+ else {
+ printf("Connected to remote host.\n");
+ }
+
+
+ if (nodelay) tcp_setflags(s,TCPFLG_NODELAY);
+
+ connflag = TRUE;
+ for (;;) {
+ tcp_status(s,&connflag,&rxdata,NULL);
+ if (connflag != TCPSTATUS_CONNECTED) {
+ printf("Remote host is no longer connected.\n");
+ break;
+ }
+ if (rxdata != 0) {
+ res = tcp_recv(s,data,sizeof(data));
+ if (res > 0) {
+ if (quiet) {
+ total += res;
+ if (total > 1000000) {
+ total -= 1000000;
+ printf(".");
+ }
+ }
+ else {
+ console_write(data,res);
+ }
+ }
+ if (res < 0) {
+ ui_showerror(res,"TCP read error");
+ }
+ }
+ if (console_status()) {
+ console_read(data,1);
+ if (data[0] == 1) break;
+ else if (data[0] == 3) break;
+ else if (data[0] == 4) {
+ for (res = 0; res < 100; res++) data[res] = 'A'+(res%26);
+ tcp_send(s,data,100);
+ }
+ else if (data[0] == 5) tcp_send(s,bigbuf,2048);
+ else if (data[0] == 2) tcp_debug(s,0);
+ else tcp_send(s,data,1);
+ }
+ if (discard) {
+ res = rand() % sizeof(data);
+ memset(data,b,res);
+ b++;
+ res = tcp_send(s,data,res);
+ if (res > 0) {
+ total2 += res;
+ if (total2 > 1000000) {
+ total2 -= 1000000;
+ printf("+");
+ }
+ }
+
+ }
+
+ POLL();
+ }
+
+ printf("Disconnecting...");
+ tcp_close(s);
+ printf("done.\n");
+
+ KFREE(bigbuf);
+
+ return 0;
+}
+
+
+static int ui_cmd_listen(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int s;
+ char *port;
+ int res;
+ int connflag;
+ int rxdata;
+ uint8_t data[100];
+ int quiet;
+ int discard;
+ int total = 0;
+ int total2 = 0;
+ char b = 0;
+ char *bigbuf;
+ uint16_t p;
+ uint16_t remport;
+ uint8_t remaddr[IP_ADDR_LEN];
+ int nodelay;
+
+ bigbuf = KMALLOC(4096,0);
+ for (res = 0; res < 4096; res++) bigbuf[res] = 'A'+(res%26);
+
+ quiet = cmd_sw_isset(cmd,"-q");
+ discard = cmd_sw_isset(cmd,"-d");
+ nodelay = cmd_sw_isset(cmd,"-nodelay");
+
+ port = cmd_getarg(cmd,0);
+ if (!port) port = "1234";
+ p = atoi(port);
+
+ s = tcp_socket();
+
+ if (s < 0) {
+ return ui_showerror(s,"Could not create TCP socket");
+ }
+
+ res = tcp_listen(s,p);
+ if (res < 0) {
+ ui_showerror(res,"Could not set socket to listen");
+ tcp_close(s);
+ return res;
+ }
+
+ printf("Listening...");
+ connflag = FALSE;
+ for (;;) {
+ if (console_status()) break;
+ tcp_status(s,&connflag,NULL,NULL);
+ if (connflag == TCPSTATUS_CONNECTED) break;
+ POLL();
+ }
+
+ if (connflag != TCPSTATUS_CONNECTED) {
+ printf("No connection received from remote host\n");
+ tcp_close(s);
+ return -1;
+ }
+
+ tcp_peeraddr(s,remaddr,&remport);
+ printf("Connection from port %u on %I\n",remport,remaddr);
+
+ if (nodelay) tcp_setflags(s,TCPFLG_NODELAY);
+
+ connflag = TRUE;
+ for (;;) {
+ tcp_status(s,&connflag,&rxdata,NULL);
+ if (connflag != TCPSTATUS_CONNECTED) {
+ printf("Remote host is no longer connected.\n");
+ break;
+ }
+ if (rxdata != 0) {
+ res = tcp_recv(s,data,sizeof(data));
+ if (res > 0) {
+ if (quiet) {
+ total += res;
+ if (total > 1000000) {
+ total -= 1000000;
+ printf(".");
+ }
+ }
+ else {
+ console_write(data,res);
+ }
+ }
+ if (res < 0) {
+ ui_showerror(res,"TCP read error");
+ }
+ }
+ if (console_status()) {
+ console_read(data,1);
+ if (data[0] == 1) break;
+ if (data[0] == 3) break;
+ if (data[0] == 4) {
+ for (res = 0; res < 100; res++) data[res] = 'A'+(res%26);
+ tcp_send(s,data,100);
+ }
+ if (data[0] == 5) tcp_send(s,bigbuf,2048);
+ if (data[0] == 2) tcp_debug(s,0);
+ else tcp_send(s,data,1);
+ }
+ if (discard) {
+ res = rand() % sizeof(data);
+ memset(data,b,res);
+ b++;
+ res = tcp_send(s,data,res);
+ if (res > 0) {
+ total2 += res;
+ if (total2 > 1000000) {
+ total2 -= 1000000;
+ printf("+");
+ }
+ }
+
+ }
+
+ POLL();
+ }
+
+
+ printf("Disconnecting...");
+ tcp_close(s);
+ printf("done.\n");
+
+ KFREE(bigbuf);
+
+ return 0;
+}
+
+
+static int ui_cmd_tcpconstest(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *x;
+ int fh;
+ int res;
+ uint8_t data[100];
+
+ x = cmd_getarg(cmd,0);
+ if (!x) return ui_showusage(cmd);
+
+ fh = cfe_open(x);
+ if (fh < 0) return ui_showerror(fh,"Could not open device %s",x);
+
+ for (;;) {
+ if (console_status()) break;
+ res = cfe_read(fh,data,sizeof(data));
+ if (res < 0) {
+ ui_showerror(res,"could not read data");
+ break;
+ }
+ console_write(data,res);
+ }
+
+ cfe_close(fh);
+
+ return 0;
+}
+
+static int ui_cmd_ttcp(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int s;
+ uint8_t hostaddr[IP_ADDR_LEN];
+ char *host;
+ int res;
+ int totalbytes = 0;
+ int totalbufs = 0;
+ cfe_timer_t start_time;
+ cfe_timer_t stop_time;
+ cfe_timer_t t;
+ int connflag;
+ char *bigbuf;
+ int nodelay;
+ int numbuf;
+ int buflen;
+ int txmode,rxmode;
+ uint16_t port;
+
+ char *x;
+
+ if (cmd_sw_value(cmd,"-n",&x)) numbuf = atoi(x);
+ else numbuf = 2048;
+
+ if (cmd_sw_value(cmd,"-l",&x)) buflen = atoi(x);
+ else buflen = 2048;
+
+ if (cmd_sw_value(cmd,"-p",&x)) port = atoi(x);
+ else port = 5001;
+
+ if ((numbuf == 0) || (buflen == 0)) return ui_showusage(cmd);
+
+
+ bigbuf = KMALLOC(buflen,0);
+ for (res = 0; res < buflen; res++) bigbuf[res] = 'A'+(res%26);
+
+ txmode = cmd_sw_isset(cmd,"-t");
+ rxmode = cmd_sw_isset(cmd,"-r");
+
+ if (!(txmode ^ rxmode)) {
+ return ui_showerror(-1,"You must specify one of -t or -r");
+ }
+
+ nodelay = cmd_sw_isset(cmd,"-D");
+
+ if (txmode) {
+ host = cmd_getarg(cmd,0);
+ if (!host) return ui_showusage(cmd);
+
+ if (isdigit(*host)) {
+ if (parseipaddr(host,hostaddr) < 0) {
+ return ui_showerror(-1,"Invalid IP address: %s\n",host);
+ }
+ }
+ else {
+ res = dns_lookup(host,hostaddr);
+ if (res < 0) {
+ return ui_showerror(res,"Could not resolve IP address of host %s",host);
+ }
+ }
+ }
+
+
+ s = tcp_socket();
+
+ if (s < 0) {
+ return ui_showerror(s,"Could not create TCP socket");
+ }
+
+
+ if (txmode) {
+ res = tcp_connect(s,hostaddr,port);
+ if (res < 0) {
+ ui_showerror(res,"Could not connect to host %I",hostaddr);
+ tcp_close(s);
+ return res;
+ }
+
+ TIMER_SET(t,CFE_HZ*30);
+ connflag = 0;
+ while (!TIMER_EXPIRED(t)) {
+ POLL();
+ tcp_status(s,&connflag,NULL,NULL);
+ if (connflag == TCPSTATUS_CONNECTING) continue;
+ break;
+ }
+
+ if (connflag != TCPSTATUS_CONNECTED) {
+ printf("Could not connect to remote host\n");
+ tcp_close(s);
+ return -1;
+ }
+ else {
+ printf("Connected to remote host.\n");
+ }
+ }
+
+ if (rxmode) {
+ printf("Waiting for connection on port %d: ",port);
+ tcp_listen(s,port);
+ for (;;) {
+ if (console_status()) break;
+ tcp_status(s,&connflag,NULL,NULL);
+ if (connflag == TCPSTATUS_CONNECTED) break;
+ POLL();
+ }
+ if (connflag != TCPSTATUS_CONNECTED) {
+ printf("No connection received from remote host\n");
+ tcp_close(s);
+ return -1;
+ }
+ printf("done.\n");
+ }
+
+
+ if (nodelay) tcp_setflags(s,TCPFLG_NODELAY); /* also sets blocking */
+ else tcp_setflags(s,0);
+
+ start_time = cfe_ticks;
+
+ if (rxmode) {
+ while (1) {
+ POLL();
+ res = tcp_recv(s,bigbuf,buflen);
+ if (res != buflen) break;
+ totalbytes += res;
+ totalbufs++;
+ }
+ }
+ else {
+ while (numbuf > 0) {
+ POLL();
+ res = tcp_send(s,bigbuf,buflen);
+ if (res != buflen) break;
+ numbuf--;
+ totalbytes += res;
+ totalbufs++;
+ }
+ }
+
+ stop_time = cfe_ticks;
+
+ tcp_close(s);
+
+ if ((res < 0) && !rxmode) {
+ ui_showerror(res,"Network I/O error");
+ }
+ else {
+ printf("%d bytes transferred via %d calls in %lld ticks\n",
+ totalbytes,totalbufs,stop_time-start_time);
+ }
+
+
+ KFREE(bigbuf);
+
+ return 0;
+
+}
+
+#endif /* CFG_TCP */
diff --git a/cfe/cfe/ui/ui_test_disk.c b/cfe/cfe/ui/ui_test_disk.c
new file mode 100644
index 0000000..9e3e5f9
--- /dev/null
+++ b/cfe/cfe/ui/ui_test_disk.c
@@ -0,0 +1,439 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Commands to test block devices File: ui_test_disk.c
+ *
+ * Commands to manipulate block devices live here.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_error.h"
+#include "cfe_ioctl.h"
+#include "cfe_devfuncs.h"
+#include "ui_command.h"
+#include "cfe.h"
+
+#include "cfe_fileops.h"
+#include "cfe_bootblock.h"
+#include "cfe_boot.h"
+
+static int ui_cmd_disktest(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_fstest(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_copydisk(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_bootblock(ui_cmdline_t *cmd,int argc,char *argv[]);
+
+int ui_init_disktestcmds(void);
+
+int ui_init_disktestcmds(void)
+{
+
+ cmd_addcmd("test disk",
+ ui_cmd_disktest,
+ NULL,
+ "Do a disk test, read/write sectors on the disk",
+ "test disk device-name [-random | sector# | {-w sector offset byte}]",
+ "-random;|"
+ "-w;Write a byte at offset in sector.**DANGER!! BE CAREFUL WHICH DEVICE YOU WRITE TO.**");
+
+ cmd_addcmd("test fatfs",
+ ui_cmd_fstest,
+ NULL,
+ "Do a FAT file system test",
+ "test fatfs device-name",
+ "");
+
+ cmd_addcmd("copydisk",
+ ui_cmd_copydisk,
+ NULL,
+ "Copy a remote disk image to a local disk device via TFTP",
+ "copydisk host:filename device-name [offset]",
+ "");
+
+ cmd_addcmd("show boot",
+ ui_cmd_bootblock,
+ NULL,
+ "Display boot block from device,",
+ "show boot device-name\n\n"
+ "This command displays the boot block on the specified device. The\n"
+ "device-name parameter identifies a block device (disk, tape, CD-ROM)\n"
+ "to be scanned for boot blocks. The first boot block found will be\n"
+ "displayed.",
+ "");
+ return 0;
+}
+
+
+static unsigned long rand(void)
+{
+ static unsigned long seed = 1;
+ long x, hi, lo, t;
+
+ x = seed;
+ hi = x / 127773;
+ lo = x % 127773;
+ t = 16807 * lo - 2836 * hi;
+ if (t <= 0) t += 0x7fffffff;
+ seed = t;
+ return t;
+}
+
+
+static int ui_cmd_bootblock(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int fh;
+ char *tok;
+ struct boot_block bootblock;
+ int res;
+ int idx;
+ int sec;
+ uint32_t checksum;
+ uint32_t checksumd;
+ uint32_t calcsum;
+ uint32_t secsize;
+ uint64_t secoffset;
+ uint8_t *code;
+
+ tok = cmd_getarg(cmd,0);
+ if (!tok) return -1;
+
+ fh = cfe_open(tok);
+ if (fh < 0) {
+ xprintf("Could not open device; %d\n",fh);
+ return -1;
+ }
+ for (sec = 0; sec < BOOT_BLOCK_MAXLOC; sec++) {
+ res = cfe_readblk(fh,sec * BOOT_BLOCK_BLOCKSIZE,
+ (unsigned char *) &bootblock,sizeof(bootblock));
+
+ if (bootblock.bb_magic != BOOT_MAGIC_NUMBER) {
+ continue;
+ }
+ xprintf("Found boot block in sector %d\n", sec);
+ if (res != sizeof(bootblock)) {
+ xprintf("Could not read boot block\n");
+ cfe_close(fh);
+ return -1;
+ }
+
+ xprintf("Boot block data:\n");
+ for (idx = 59; idx < 64; idx++) {
+ xprintf(" %d: %016llX\n",idx,bootblock.bb_data[idx]);
+ }
+ xprintf("\n");
+
+ xprintf("Boot block version is %d\n",
+ (uint32_t) ((bootblock.bb_hdrinfo & BOOT_HDR_VER_MASK) >> BOOT_HDR_VER_SHIFT));
+ xprintf("Boot block flags are %02X\n",
+ (uint32_t) ((bootblock.bb_hdrinfo & BOOT_HDR_FLAGS_MASK) >> 56));
+ checksum = ((uint32_t) (bootblock.bb_hdrinfo & BOOT_HDR_CHECKSUM_MASK));
+ checksumd = ((uint32_t) ((bootblock.bb_secsize & BOOT_DATA_CHECKSUM_MASK) >> BOOT_DATA_CHECKSUM_SHIFT));
+ bootblock.bb_hdrinfo &= ~BOOT_HDR_CHECKSUM_MASK;
+ secsize = ((uint32_t) (bootblock.bb_secsize & BOOT_SECSIZE_MASK));
+ secoffset = bootblock.bb_secstart;
+
+ xprintf("Boot code is %d bytes at %016llX\n",secsize,secoffset);
+
+ CHECKSUM_BOOT_DATA(&(bootblock.bb_magic),BOOT_BLOCK_SIZE,&calcsum);
+
+ if (checksum != calcsum) {
+ xprintf("Header checksum does not match Blk=%08X Calc=%08X\n",
+ checksum,calcsum);
+ }
+ else {
+ xprintf("Header checksum is ok\n");
+ }
+
+ code = KMALLOC(secsize,0);
+ if (code) {
+ res = cfe_readblk(fh,secoffset,code,secsize);
+ if (res != secsize) {
+ xprintf("Could not read boot code\n");
+ cfe_close(fh);
+ KFREE(code);
+ return -1;
+ }
+ CHECKSUM_BOOT_DATA(code,secsize,&calcsum);
+ if (calcsum == checksumd) xprintf("Boot code checksum is ok\n");
+ else xprintf("Boot code checksum is incorrect (Calc=%08X, Blk=%08X)\n",
+ calcsum,checksumd);
+ KFREE(code);
+ }
+ break;
+ }
+ if (sec == BOOT_BLOCK_MAXLOC) {
+ xprintf("No valid boot blocks found in the first %d sectors\n",
+ BOOT_BLOCK_MAXLOC);
+ }
+ cfe_close(fh);
+
+ return 0;
+}
+
+
+
+
+
+extern int fatfs_fileop_dir(void *fsctx);
+
+static int ui_cmd_fstest(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *tok;
+ char *fname;
+ fileio_ctx_t *fsctx;
+ void *filectx;
+ uint8_t buffer[1000];
+ int res;
+ int total;
+
+ tok = cmd_getarg(cmd,0);
+ if (!tok) return -1;
+
+ fname = cmd_getarg(cmd,1);
+
+ res = fs_init("fat",&fsctx,tok);
+ if (res < 0) {
+ xprintf("Could not init file system: %s\n",cfe_errortext(res));
+ return res;
+ }
+
+ if (!fname) {
+ fatfs_fileop_dir(fsctx->fsctx);
+ }
+ else {
+ res = fs_open(fsctx,&filectx,fname,FILE_MODE_READ);
+ if (res < 0) {
+ xprintf("Could not open %s: %s\n",fname,cfe_errortext(res));
+ }
+ else {
+
+ total = 0;
+ for (;;) {
+ res = fs_read(fsctx,filectx,buffer,sizeof(buffer));
+ if (res < 0) break;
+ total += res;
+ if (res != sizeof(buffer)) break;
+ xprintf(".");
+ }
+ if (res < 0) xprintf("read error %s\n",cfe_errortext(res));
+ else xprintf("Total bytes read: %d\n",total);
+ fs_close(fsctx,filectx);
+ }
+ }
+
+ fs_uninit(fsctx);
+ return 0;
+}
+
+static int ui_cmd_copydisk(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *fname;
+ fileio_ctx_t *fsctx;
+ void *filectx;
+ char *devname;
+ uint8_t buffer[1024];
+ int fh;
+ int res;
+ int total;
+ int count;
+ int offset;
+ char *toffset;
+
+ fname = cmd_getarg(cmd,0);
+ if (!fname) return ui_showusage(cmd);
+
+ devname = cmd_getarg(cmd,1);
+ if (!devname) return ui_showusage(cmd);
+
+ toffset = cmd_getarg(cmd,2);
+ if (!toffset) offset = 0; else offset = atoi(toffset);
+
+ if ((cfe_getdevinfo(devname) & CFE_DEV_MASK) != CFE_DEV_DISK) {
+ xprintf("Device %s is not a disk.\n",devname);
+ return CFE_ERR_INV_PARAM;
+ }
+
+ fh = cfe_open(devname);
+ if (fh < 0) {
+ return ui_showerror(fh,"Could not open device %s",devname);
+ }
+
+ res = fs_init("tftp",&fsctx,"");
+ if (res < 0) {
+ return ui_showerror(res,"Could not init file system");
+ }
+
+ res = fs_open(fsctx,&filectx,fname,FILE_MODE_READ);
+ if (res < 0) {
+ return ui_showerror(res,"Could not open %s",fname);
+ }
+ else {
+ total = 0;
+ count = 0;
+ for (;;) {
+ res = fs_read(fsctx,filectx,buffer,sizeof(buffer));
+ if (res < 0) break;
+ if (res > 0) cfe_writeblk(fh,total+offset*512,buffer,res);
+ total += res;
+ if (res != sizeof(buffer)) break;
+ count++;
+ if (count == 256) {
+ xprintf(".");
+ count = 0;
+ }
+ }
+ if (res < 0) xprintf("read error %s\n",cfe_errortext(res));
+ else xprintf("Total bytes read: %d\n",total);
+ fs_close(fsctx,filectx);
+ }
+
+ fs_uninit(fsctx);
+ cfe_close(fh);
+ return 0;
+}
+
+static int ui_cmd_disktest(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int fh;
+ char *tok;
+ char *tok2;
+ char *tok3;
+ char *tok4;
+ cfe_offset_t offset;
+ uint64_t sectors;
+ int secsize;
+ long secnum = 0;
+ unsigned char buffer[2048];
+ int res;
+ int idx,idx2;
+ int count = 0;
+ uint8_t byte;
+ int secoffset = 0;
+
+ tok = cmd_getarg(cmd,0);
+ if (!tok) return -1;
+
+ tok2 = cmd_getarg(cmd,1);
+ tok3 = cmd_getarg(cmd,2);
+ tok4 = cmd_getarg(cmd,3);
+
+ fh = cfe_open(tok);
+ if (fh <= 0) {
+ xprintf("Could not open device: %s\n",cfe_errortext(fh));
+ return fh;
+ }
+
+ xprintf("device opened ok\n");
+
+ sectors = 0; secsize = 0;
+ cfe_ioctl(fh,IOCTL_BLOCK_GETTOTALBLOCKS,(uint8_t *) &sectors,sizeof(sectors),&res,0);
+ cfe_ioctl(fh,IOCTL_BLOCK_GETBLOCKSIZE,(uint8_t *) &secsize,sizeof(secsize),&res,0);
+ printf("Total sectors: %lld Sector size: %d\n",sectors,secsize);
+ if (secsize == 0) secsize = 512;
+ if (sectors == 0) sectors = 100000;
+
+ if (tok2) {
+ secnum = atoi(tok2);
+ offset = (cfe_offset_t) secnum * (cfe_offset_t) secsize;
+ if (cmd_sw_isset(cmd,"-w")) {
+ secoffset = atoi(tok3);
+ byte = (uint8_t) xtoq(tok4);
+ res = cfe_writeblk(fh,offset+secoffset,&byte,1);
+ if (res != 1) {
+ xprintf("Write failed\n");
+ return -1;
+ }
+ }
+ res = cfe_readblk(fh,offset,buffer,secsize);
+ if (res != secsize) {
+ xprintf("disk error: %d sector %d\n",res,secnum);
+ }
+ else {
+ for (idx = 0; idx < secsize; idx+=16) {
+ xprintf("%04X: ",idx);
+ for (idx2 = 0; idx2 < 16; idx2++) {
+ xprintf("%02X ",buffer[idx+idx2]);
+ }
+ for (idx2 = 0; idx2 < 16; idx2++) {
+ if ((buffer[idx+idx2] < 32) ||
+ (buffer[idx+idx2] > 127)) {
+ xprintf(".");
+ }
+ else {
+ xprintf("%c",buffer[idx+idx2]);
+ }
+ }
+ xprintf("\n");
+ }
+ }
+ }
+ else {
+ if (cmd_sw_isset(cmd,"-random")) {
+ while (!console_status()) {
+ secnum++;
+ secnum = rand() % sectors;
+ offset = (cfe_offset_t) secnum * (cfe_offset_t) secsize;
+ res = cfe_readblk(fh,offset,buffer,secsize);
+ if (res != secsize) {
+ xprintf("disk error: %d sector %d\n",res,secnum);
+ break;
+ }
+ count++;
+ if ((count % 1000) == 0) xprintf("%d ",count);
+ }
+ }
+ }
+
+ cfe_close(fh);
+
+ return 0;
+}
+
+
+
diff --git a/cfe/cfe/ui/ui_test_ether.c b/cfe/cfe/ui/ui_test_ether.c
new file mode 100644
index 0000000..9a0b328
--- /dev/null
+++ b/cfe/cfe/ui/ui_test_ether.c
@@ -0,0 +1,202 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Ethernet test commands File: ui_test_ether.c
+ *
+ * User interface commands to test Ethernet devices
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_error.h"
+#include "cfe_ioctl.h"
+#include "cfe_devfuncs.h"
+#include "ui_command.h"
+#include "cfe.h"
+
+typedef struct netparam_s {
+ const char *str;
+ int num;
+} netparam_t;
+
+const static netparam_t speedtypes[] = {
+ {"auto",ETHER_SPEED_AUTO},
+ {"10hdx",ETHER_SPEED_10HDX},
+ {"10fdx",ETHER_SPEED_10FDX},
+ {"100hdx",ETHER_SPEED_100HDX},
+ {"100fdx",ETHER_SPEED_100FDX},
+ {"1000hdx",ETHER_SPEED_1000HDX},
+ {"1000fdx",ETHER_SPEED_1000FDX},
+ {0,NULL}};
+
+
+int ui_init_ethertestcmds(void);
+
+static int ui_cmd_ethertest(ui_cmdline_t *cmd,int argc,char *argv[]);
+
+int ui_init_ethertestcmds(void)
+{
+ cmd_addcmd("test ether",
+ ui_cmd_ethertest,
+ NULL,
+ "Do an ethernet test, reading packets from the net",
+ "test ether device-name",
+ "-speed=*;Specify speed|"
+ "-q;Be quiet|"
+ "-send=*;Transmit packets"
+ );
+
+ return 0;
+}
+
+
+static int ui_ifconfig_lookup(char *name,char *val,const netparam_t *list)
+{
+ const netparam_t *p = list;
+
+ while (p->str) {
+ if (strcmp(p->str,val) == 0) return p->num;
+ p++;
+ }
+
+ xprintf("Invalid parameter for %s: Valid options are: ");
+
+ p = list;
+ while (p->str) {
+ xprintf("%s ",p->str);
+ p++;
+ }
+
+ xprintf("\n");
+ return -1;
+}
+
+static int ui_cmd_ethertest(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *tok;
+ int fh;
+ uint8_t packet[2048];
+ int res;
+ int idx;
+ int speed = ETHER_SPEED_AUTO;
+ char *x;
+ int count = 0;
+ int quiet;
+
+ tok = cmd_getarg(cmd,0);
+ if (!tok) return -1;
+
+ if (cmd_sw_value(cmd,"-speed",&x)) {
+ speed = ui_ifconfig_lookup("-speed",x,speedtypes);
+ if (speed < 0) return CFE_ERR_INV_PARAM;
+ }
+
+ quiet = cmd_sw_isset(cmd,"-q");
+
+
+ fh = cfe_open(tok);
+ if (fh < 0) {
+ xprintf("Could not open device: %s\n",cfe_errortext(fh));
+ return fh;
+ }
+
+ if (speed != ETHER_SPEED_AUTO) {
+ xprintf("Setting speed to %d...\n",speed);
+ cfe_ioctl(fh,IOCTL_ETHER_SETSPEED,(uint8_t *) &speed,sizeof(speed),&idx,0);
+ }
+
+
+ if (cmd_sw_value(cmd,"-send",&x)) {
+ count = atoi(x);
+ memset(packet,0xEE,sizeof(packet));
+ memcpy(packet,"\xFF\xFF\xFF\xFF\xFF\xFF\x40\x00\x00\x10\x00\x00\x12\x34",16);
+ res = 0;
+ for (idx = 0; idx < count; idx++) {
+ res = cfe_write(fh,packet,128);
+ if (res < 0) break;
+ }
+ if (res) {
+ ui_showerror(res,"Could not transmit packet");
+ }
+ cfe_close(fh);
+ return 0;
+ }
+
+ xprintf("Receiving... press enter to stop\n");
+ while (!console_status()) {
+ res = cfe_read(fh,packet,sizeof(packet));
+ if (res == 0) continue;
+ if (res < 0) {
+ xprintf("Read error: %s\n",cfe_errortext(res));
+ break;
+ }
+
+ if (!quiet) {
+ xprintf("%4d ",res);
+ if (res > 32) res = 32;
+
+ for (idx = 0; idx < res; idx++) {
+ xprintf("%02X",packet[idx]);
+ if ((idx == 5) || (idx == 11) || (idx == 13)) xprintf(" ");
+ }
+
+ xprintf("\n");
+ }
+
+ count++;
+ if (quiet && !(count % 1000)) printf(".");
+ }
+
+ printf("Total packets received: %d\n",count);
+
+ cfe_close(fh);
+
+ return 0;
+}
+
diff --git a/cfe/cfe/ui/ui_test_flash.c b/cfe/cfe/ui/ui_test_flash.c
new file mode 100644
index 0000000..841d3fa
--- /dev/null
+++ b/cfe/cfe/ui/ui_test_flash.c
@@ -0,0 +1,260 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Flash Test commands File: ui_test_flash.c
+ *
+ * Some commands to test the flash device interface.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_devfuncs.h"
+#include "cfe_timer.h"
+#include "cfe_ioctl.h"
+
+#include "cfe_error.h"
+
+#include "ui_command.h"
+
+int ui_init_flashtestcmds(void);
+
+static int ui_cmd_flashtest(ui_cmdline_t *cmd,int argc,char *argv[]);
+//static int ui_cmd_readnvram(ui_cmdline_t *cmd,int argc,char *argv[]);
+//static int ui_cmd_erasenvram(ui_cmdline_t *cmd,int argc,char *argv[]);
+
+int ui_init_flashtestcmds(void)
+{
+ cmd_addcmd("show flash",
+ ui_cmd_flashtest,
+ NULL,
+ "Display information about a flash device.",
+ "show flash [-sectors]",
+ "-sectors;Display sector information");
+
+#if 0
+ cmd_addcmd("nvram read",
+ ui_cmd_readnvram,
+ NULL,
+ "read the NVRAM",
+ "test nvram devname offset",
+ "");
+
+ cmd_addcmd("nvram erase",
+ ui_cmd_erasenvram,
+ NULL,
+ "erase the NVRAM",
+ "erasenvram devname",
+ "-pattern");
+#endif
+
+
+ return 0;
+}
+
+
+static char *flashtypes[] = {
+ "Unknown","SRAM","ROM","Flash"
+};
+
+
+static int ui_cmd_flashtest(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ flash_info_t info;
+ int fd;
+ int retlen;
+ int res = 0;
+ int idx;
+ flash_sector_t sector;
+ nvram_info_t nvraminfo;
+ char *devname;
+ int showsectors;
+
+ devname = cmd_getarg(cmd,0);
+ if (!devname) return ui_showusage(cmd);
+
+ showsectors = cmd_sw_isset(cmd,"-sectors");
+
+ fd = cfe_open(devname);
+ if (fd < 0) {
+ ui_showerror(fd,"Could not open flash device %s",devname);
+ return fd;
+ }
+
+ res = cfe_ioctl(fd,IOCTL_FLASH_GETINFO,(uint8_t *) &info,sizeof(flash_info_t),&retlen,0);
+ if (res == 0) {
+ printf("FLASH: Base %016llX size %08X type %02X(%s) flags %08X\n",
+ info.flash_base,info.flash_size,info.flash_type,flashtypes[info.flash_type],
+ info.flash_flags);
+ }
+ else {
+ printf("FLASH: Could not determine flash information\n");
+ }
+
+ res = cfe_ioctl(fd,IOCTL_NVRAM_GETINFO,(uint8_t *) &nvraminfo,sizeof(nvram_info_t),&retlen,0);
+ if (res == 0) {
+ printf("NVRAM: Offset %08X Size %08X EraseFlg %d\n",
+ nvraminfo.nvram_offset,nvraminfo.nvram_size,nvraminfo.nvram_eraseflg);
+ }
+ else {
+ printf("NVRAM: Not supported by this flash\n");
+ }
+
+ if (showsectors && (info.flash_type == FLASH_TYPE_FLASH)) {
+ printf("Flash sector information:\n");
+
+ idx = 0;
+ for (;;) {
+ sector.flash_sector_idx = idx;
+ res = cfe_ioctl(fd,IOCTL_FLASH_GETSECTORS,(uint8_t *) &sector,sizeof(flash_sector_t),&retlen,0);
+ if (res != 0) {
+ printf("ioctl error\n");
+ break;
+ }
+ if (sector.flash_sector_status == FLASH_SECTOR_INVALID) break;
+ printf(" Sector %d offset %08X size %d\n",
+ sector.flash_sector_idx,
+ sector.flash_sector_offset,
+ sector.flash_sector_size);
+ idx++;
+ }
+ }
+
+ cfe_close(fd);
+ return 0;
+
+}
+
+
+#if 0
+static int ui_cmd_readnvram(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *dev;
+ char *tok;
+ int fd;
+ int offset = 0;
+ int res;
+ uint8_t buf[512];
+ int idx;
+
+ dev = cmd_getarg(cmd,0);
+ if (!dev) return ui_showusage(cmd);
+
+ tok = cmd_getarg(cmd,1);
+ if (tok) offset = xtoi(tok);
+ else offset = 0;
+
+ fd = cfe_open(dev);
+ if (fd < 0) {
+ ui_showerror(fd,"could not open NVRAM");
+ return fd;
+ }
+
+ res = cfe_readblk(fd,offset,buf,512);
+ printf("Offset %d Result %d\n",offset,res);
+ for (idx = 0; idx < 512; idx++) {
+ if ((idx % 16) == 0) printf("\n");
+ printf("%02X ",buf[idx]);
+ }
+ printf("\n");
+
+ cfe_close(fd);
+ return 0;
+
+}
+
+static int ui_cmd_erasenvram(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *dev;
+ int fd;
+ uint8_t buffer[2048];
+ int res;
+ char *tok;
+ int offset;
+ int length;
+ uint8_t data;
+
+ dev = cmd_getarg(cmd,0);
+ if (!dev) return ui_showusage(cmd);
+
+ offset = 0;
+ if ((tok = cmd_getarg(cmd,1))) offset = xtoi(tok);
+ length = 512;
+
+ if ((tok = cmd_getarg(cmd,2))) length = xtoi(tok);
+ if (length > 2048) length = 2048;
+
+ data = 0xFF;
+ if ((tok = cmd_getarg(cmd,3))) data = xtoi(tok);
+
+ fd = cfe_open(dev);
+ if (fd < 0) {
+ ui_showerror(fd,"could not open NVRAM");
+ return fd;
+ }
+
+ if (cmd_sw_isset(cmd,"-pattern")) {
+ memset(buffer,0,sizeof(buffer));
+ for (res = 0; res < 2048; res++) {
+ buffer[res] = res & 0xFF;
+ }
+ }
+ else memset(buffer,data,sizeof(buffer));
+
+ printf("Fill offset %04X length %04X\n",offset,length);
+
+ res = cfe_writeblk(fd,offset,buffer,length);
+
+ printf("write returned %d\n",res);
+
+ cfe_close(fd);
+ return 0;
+
+}
+#endif
+
diff --git a/cfe/cfe/ui/ui_test_uart.c b/cfe/cfe/ui/ui_test_uart.c
new file mode 100644
index 0000000..3eeaef0
--- /dev/null
+++ b/cfe/cfe/ui/ui_test_uart.c
@@ -0,0 +1,117 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * UART Test commands File: ui_test_uart.c
+ *
+ * Some commands to test the uart device interface.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_devfuncs.h"
+#include "cfe_timer.h"
+#include "cfe_ioctl.h"
+
+#include "cfe_error.h"
+
+#include "ui_command.h"
+
+int ui_init_uarttestcmds(void);
+
+static int ui_cmd_uarttest(ui_cmdline_t *cmd,int argc,char *argv[]);
+
+int ui_init_uarttestcmds(void)
+{
+ cmd_addcmd("test uart",
+ ui_cmd_uarttest,
+ NULL,
+ "Echo characters to a UART",
+ "test uart [devname]",
+ "");
+ return 0;
+}
+
+
+static int ui_cmd_uarttest(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int fd;
+ char *x;
+ char ch;
+ int res;
+ char buffer[64];
+
+ x = cmd_getarg(cmd,0);
+ if (!x) return ui_showusage(cmd);
+
+ fd = cfe_open(x);
+ if (fd < 0) {
+ ui_showerror(fd,"could not open %s",x);
+ return fd;
+ }
+
+ printf("Device open. Stuff you type here goes there. Type ~ to exit.\n");
+ for (;;) {
+ if (console_status()) {
+ console_read(&ch,1);
+ res = cfe_write(fd,&ch,1);
+ if (res < 0) break;
+ if (ch == '~') break;
+ }
+ if (cfe_inpstat(fd)) {
+ res = cfe_read(fd,buffer,sizeof(buffer));
+ if (res > 0) console_write(buffer,res);
+ if (res < 0) break;
+ }
+ POLL();
+ }
+
+ cfe_close(fd);
+ return 0;
+}
+
diff --git a/cfe/cfe/ui/ui_tftpd.c b/cfe/cfe/ui/ui_tftpd.c
new file mode 100755
index 0000000..6cd2e4e
--- /dev/null
+++ b/cfe/cfe/ui/ui_tftpd.c
@@ -0,0 +1,119 @@
+/***************************************************************************
+***
+*** Copyright 2005 Hon Hai Precision Ind. Co. Ltd.
+*** All Rights Reserved.
+*** No portions of this material shall be reproduced in any form without the
+*** written permission of Hon Hai Precision Ind. Co. Ltd.
+***
+*** All information contained in this document is Hon Hai Precision Ind.
+*** Co. Ltd. company private, proprietary, and trade secret property and
+*** are protected by international intellectual property laws and treaties.
+***
+****************************************************************************/
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_ioctl.h"
+#include "cfe_timer.h"
+#include "cfe_error.h"
+
+#include "ui_command.h"
+#include "cfe.h"
+
+#include "cfe_fileops.h"
+#include "cfe_boot.h"
+#include "bsp_config.h"
+
+#include "cfe_loader.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+#include "net_api.h"
+
+#include "cfe_flashimage.h"
+
+#include "addrspace.h"
+#include "initdata.h"
+#include "url.h"
+
+#include "tftpd.h"
+
+int ui_init_tftpdcmds(void);
+
+static int tftpd_state = TFTPD_STATE_OFF;
+
+extern int tftp_recv_timeout;
+
+int get_tftpd_state(void)
+{
+ return tftpd_state;
+}
+
+int set_tftpd_state(int state)
+{
+ tftpd_state = state;
+ return 0;
+}
+
+static int ui_cmd_tftpd(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int ret;
+
+ xprintf("enter ui_cmd_tftpd \n");
+
+ if( (argc==1) && strcmp(argv[0], "nmrp") == 0 )
+ {
+ xprintf("Start TFTP server for nmrp \n");
+ ret = ui_docommand("flashimage nmrp");
+ if (ret == CFE_ERR_TIMEOUT || ret == CFE_ERR_BADIMAGE || ret == CFE_ERR_IOERR || (ret == -24))
+ {
+ //printf("Upgrade image failed!\n");
+ return -1;
+ }
+ else
+ {
+ //printf("Upgrade image success!\n");
+ return 0;
+ }
+
+
+ }
+ else
+ {
+ xprintf("Start TFTP server\n");
+ /* Extend the TFTP server timeout */
+ tftp_recv_timeout = 99999;
+
+ while (1)
+ {
+ /* Foxconn modified start pling 12/04/2008 */
+ //ret = ui_docommand("flash -writechksum : flash1.trx");
+ ret = ui_docommand("flashimage :");
+ /* Foxconn modified end pling 12/04/2008 */
+ if (ret == CFE_ERR_TIMEOUT || ret == CFE_ERR_BADIMAGE || ret == CFE_ERR_IOERR)
+ continue;
+ else
+ break;
+ }
+ ui_docommand("reset");
+ return 0;
+ }
+
+}
+int ui_init_tftpdcmds(void)
+{
+ cmd_addcmd("tftpd",
+ ui_cmd_tftpd,
+ NULL,
+ "Start TFTP server",
+ "tftpd",
+ "");
+
+ return 0;
+}
diff --git a/cfe/cfe/ui/ui_toyclock.c b/cfe/cfe/ui/ui_toyclock.c
new file mode 100644
index 0000000..7fdcf49
--- /dev/null
+++ b/cfe/cfe/ui/ui_toyclock.c
@@ -0,0 +1,275 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * SWARM toy clock commands File: ui_toyclock.c
+ *
+ * time-of-year clock
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_ioctl.h"
+#include "cfe_timer.h"
+#include "cfe_error.h"
+
+#include "ui_command.h"
+#include "cfe.h"
+
+#include "bsp_config.h"
+
+/* *********************************************************************
+ * prototypes
+ ********************************************************************* */
+
+int ui_init_toyclockcmds(void);
+
+static int ui_cmd_showtime(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_settime(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_setdate(ui_cmdline_t *cmd,int argc,char *argv[]);
+
+/* *********************************************************************
+ * ui_init_toyclockcmds()
+ *
+ * Add toy clock commands to the command table
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+int ui_init_toyclockcmds(void)
+{
+
+ cmd_addcmd("show time",
+ ui_cmd_showtime,
+ NULL,
+ "Display current time according to RTC",
+ "show time",
+ "");
+
+ cmd_addcmd("set time",
+ ui_cmd_settime,
+ NULL,
+ "Set current time",
+ "set time hh:mm:ss",
+ "");
+
+ cmd_addcmd("set date",
+ ui_cmd_setdate,
+ NULL,
+ "Set current date",
+ "set date mm/dd/yyyy",
+ "");
+
+ return 0;
+}
+
+/* *********************************************************************
+ * User interface commands
+ ********************************************************************* */
+
+static int ui_cmd_settime(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *line;
+ char *p;
+ int hr,min,sec;
+ int fd;
+ uint8_t buf[12];
+ int res=0;
+
+ if ((line = cmd_getarg(cmd,0)) == NULL) {
+ return ui_showusage(cmd);
+ }
+
+ /* convert colons to spaces for the gettoken routine */
+ while ((p = strchr(line,':'))) *p = ' ';
+
+ /* parse and check command-line args */
+ hr = -1; min = -1; sec = -1;
+
+ p = gettoken(&line);
+ if (p) hr = atoi(p);
+ p = gettoken(&line);
+ if (p) min = atoi(p);
+ p = gettoken(&line);
+ if (p) sec = atoi(p);
+
+ if ((hr < 0) || (hr > 23) ||
+ (min < 0) || (min >= 60) ||
+ (sec < 0) || (sec >= 60)) {
+ return ui_showusage(cmd);
+ }
+
+ /*
+ * hour-minute-second-month-day-year1-year2-(time/date flag)
+ * time/date flag (offset 7) is used to let device know what
+ * is being set.
+ */
+ buf[0] = hr;
+ buf[1] = min;
+ buf[2] = sec;
+ buf[7] = 0x00; /*SET_TIME = 0x00, SET_DATE = 0x01*/
+
+ fd = cfe_open("clock0");
+ if (fd < 0) {
+ ui_showerror(fd,"could not open clock device");
+ return fd;
+ }
+
+ res = cfe_write(fd,buf,8);
+ if (res < 0) {
+ ui_showerror(res,"could not set time");
+ }
+ cfe_close(fd);
+ return 0;
+}
+
+static int ui_cmd_setdate(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *line;
+ char *p;
+ int dt,mo,yr,y2k;
+ int fd;
+ uint8_t buf[12];
+ int res=0;
+
+ if ((line = cmd_getarg(cmd,0)) == NULL) {
+ return ui_showusage(cmd);
+ }
+
+ /* convert colons to spaces for the gettoken routine */
+
+ while ((p = strchr(line,'/'))) *p = ' ';
+
+ /* parse and check command-line args */
+
+ dt = -1; mo = -1; yr = -1;
+
+ p = gettoken(&line);
+ if (p) mo = atoi(p);
+ p = gettoken(&line);
+ if (p) dt = atoi(p);
+ p = gettoken(&line);
+ if (p) yr = atoi(p);
+
+ if ((mo <= 0) || (mo > 12) ||
+ (dt <= 0) || (dt > 31) ||
+ (yr < 1900) || (yr > 2099)) {
+ return ui_showusage(cmd);
+ }
+
+ y2k = (yr >= 2000) ? 0x20 : 0x19;
+ yr %= 100;
+
+ /*
+ * hour-minute-second-month-day-year1-year2-(time/date flag)
+ * time/date flag (offset 7) is used to let device know what
+ * is being set.
+ */
+ buf[3] = mo;
+ buf[4] = dt;
+ buf[5] = yr;
+ buf[6] = y2k;
+ buf[7] = 0x01; /*SET_TIME = 0x00, SET_DATE = 0x01*/
+
+ fd = cfe_open("clock0");
+ if (fd < 0) {
+ ui_showerror(fd,"could not open clock device");
+ return fd;
+ }
+
+ res = cfe_write(fd,buf,8);
+ if (res < 0) {
+ ui_showerror(res,"could not set date");
+ }
+
+ cfe_close(fd);
+ return 0;
+}
+
+
+static int ui_cmd_showtime(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ uint8_t hr,min,sec;
+ uint8_t mo,day,yr,y2k;
+ int res=0;
+ int fd;
+ uint8_t buf[12];
+
+ fd = cfe_open("clock0");
+ if (fd < 0) {
+ ui_showerror(fd,"could not open clock device");
+ return fd;
+ }
+ res = cfe_read(fd,buf,8);
+ if (res < 0) {
+ ui_showerror(res,"could not get time/date");
+ }
+ cfe_close(fd);
+
+ hr = buf[0];
+ min = buf[1];
+ sec = buf[2];
+ mo = buf[3];
+ day = buf[4];
+ yr = buf[5];
+ y2k = buf[6];
+
+ printf("Current date & time is: ");
+ printf("%02X/%02X/%02X%02X %02X:%02X:%02X\n",mo,day,y2k,yr,hr,min,sec);
+
+ return 0;
+}
+
+
+
+
+
+
+
diff --git a/cfe/cfe/ui/url.c b/cfe/cfe/ui/url.c
new file mode 100644
index 0000000..80dc7b0
--- /dev/null
+++ b/cfe/cfe/ui/url.c
@@ -0,0 +1,357 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Program and file loading URLs File: url.c
+ *
+ * Functions to process URLs for loading software.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions as
+ * they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. Neither the "Broadcom
+ * Corporation" name nor any trademark or logo of Broadcom
+ * Corporation may be used to endorse or promote products
+ * derived from this software without the prior written
+ * permission of Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "bsp_config.h"
+#include "cfe_loader.h"
+#include "cfe_autoboot.h"
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+#include "cfe_fileops.h"
+#include "cfe_error.h"
+
+#include "net_ebuf.h"
+#include "net_ether.h"
+#include "net_api.h"
+
+#include "ui_command.h"
+
+#include "url.h"
+
+static long getaddr(char *str)
+{
+ /*
+ * hold on to your lunch, this is really, really bad!
+ * Make 64-bit addresses expressed as 8-digit numbers
+ * sign extend automagically. Saves typing, but is very
+ * gross. Not very portable, either.
+ */
+ int longaddr = 0;
+ long newaddr;
+
+ longaddr = strlen(str);
+ if (memcmp(str,"0x",2) == 0) longaddr -= 2;
+ longaddr = (longaddr > 8) ? 1 : 0;
+
+ if (longaddr) newaddr = (long) xtoq(str);
+ else newaddr = (long) xtoi(str);
+
+ return newaddr;
+}
+
+static int process_oldstyle(char *str,
+ ui_cmdline_t *cmd,
+ cfe_loadargs_t *la)
+{
+ char *file;
+ char *devname;
+ char *filesys = NULL;
+ char *loader = la->la_loader;
+ char *x;
+ int info;
+ char *colon;
+
+ colon = strchr(str,':');
+
+ if (!colon) {
+ return CFE_ERR_DEVNOTFOUND;
+ }
+
+ devname = str; /* will be used to check protocol later */
+ *colon = '\0';
+ file = colon + 1; /* Ugly, we might put the colon back! */
+
+ /*
+ * Try to determine the load protocol ("filesystem")
+ * first by using the command line, and
+ * if not that try to figure it out automagically
+ */
+
+ if (cmd_sw_isset(cmd,"-fatfs")) filesys = "fat";
+ if (cmd_sw_isset(cmd,"-tftp")) filesys = "tftp";
+ if (cmd_sw_isset(cmd,"-rawfs")) filesys = "raw";
+#if (CFG_TCP) && (CFG_HTTPFS)
+ if (cmd_sw_isset(cmd,"-http")) filesys = "http";
+#endif
+ if (cmd_sw_value(cmd,"-fs",&x)) filesys = x;
+
+ /*
+ * Automagic configuration
+ */
+
+ /*
+ * Determine the device type from the "host" name. If we look
+ * up the host name and it appears to be an invalid CFE device
+ * name, then it's probably a TFTP host name.
+ *
+ * This is where we guess based on the device type what
+ * sort of load method we're going to use.
+ */
+
+ info = devname ? cfe_getdevinfo(devname) : -1;
+ if (info >= 0) {
+ switch (info & CFE_DEV_MASK) {
+ case CFE_DEV_NETWORK:
+ if (!filesys) filesys = "tftp";
+ if (!loader) loader = "raw";
+ break;
+ case CFE_DEV_DISK:
+ if (!filesys) filesys = "raw";
+ if (!loader) loader = "raw";
+ break;
+ case CFE_DEV_FLASH:
+ if (!filesys) filesys = "raw";
+ if (!loader) loader = "raw";
+ break;
+ case CFE_DEV_SERIAL:
+ if (!filesys) filesys = "raw";
+ if (!loader) loader = "srec";
+ break;
+ default:
+ break;
+ }
+ la->la_device = devname;
+ la->la_filename = file;
+ }
+ else {
+ /*
+ * It's probably a network boot. Default to TFTP
+ * if not overridden
+ */
+#if CFG_NETWORK
+ la->la_device = (char *) net_getparam(NET_DEVNAME);
+#else
+ la->la_device = NULL;
+#endif
+ *colon = ':'; /* put the colon back */
+ la->la_filename = devname;
+ if (!filesys) filesys = "tftp";
+ if (!loader) loader = "raw";
+ }
+
+ /*
+ * Remember our file system and loader.
+ */
+
+ la->la_filesys = filesys;
+ la->la_loader = loader;
+
+ return 0;
+}
+
+
+#if CFG_URLS
+static int process_url(char *str,
+ ui_cmdline_t *cmd,
+ cfe_loadargs_t *la)
+{
+ char *p;
+ char *protocol;
+ int idx,len;
+ int network = 0;
+ const fileio_dispatch_t *fdisp;
+
+ /*
+ * All URLs have the string "://" in them somewhere
+ * If that's not there, try the old syntax.
+ */
+
+ len = strlen(str);
+ p = str;
+
+ for (idx = 0; idx < len-3; idx++) {
+ if (memcmp(p,"://",3) == 0) break;
+ p++;
+ }
+
+ if (idx == (len-3)) {
+ return process_oldstyle(str,cmd,la);
+ }
+
+ /*
+ * Break the string apart into protocol, host, file
+ */
+
+ protocol = str;
+ *p = '\0';
+ p += 3;
+
+ /*
+ * Determine if this is a network loader. If that is true,
+ * the meaning of the "device" field is different. Ugh.
+ */
+
+ fdisp = cfe_findfilesys(protocol);
+ if (fdisp && (fdisp->loadflags & FSYS_TYPE_NETWORK)) network = 1;
+
+ /*
+ * Depending on the protocol we parse the file name one of two ways:
+ *
+ * protocol://hostname/filename
+ *
+ * For network devices:
+ *
+ * the "device" is the current Ethernet device.
+ * The filename is the //hostname/filename from the URL.
+ *
+ * For non-network devices:
+ *
+ * The "device" is the CFE device name from the URL 'hostname' field
+ * The filename is from the URL filename field.
+ */
+
+ la->la_filesys = protocol;
+
+ if (network) {
+#if CFG_NETWORK
+ la->la_device = (char *) net_getparam(NET_DEVNAME);
+#else
+ la->la_device = NULL;
+#endif
+ la->la_filename = p;
+ }
+ else {
+ la->la_device = p;
+ p = strchr(p,'/');
+ if (p) {
+ *p++ = '\0';
+ la->la_filename = p;
+ }
+ else {
+ la->la_filename = NULL;
+ }
+ }
+
+ if (!la->la_loader) la->la_loader = "raw";
+
+ return 0;
+}
+#endif
+
+
+
+int ui_process_url(char *url,ui_cmdline_t *cmd,cfe_loadargs_t *la)
+{
+ int res;
+ char *x;
+
+ /*
+ * Skip leading whitespace
+ */
+
+ while (*url && ((*url == ' ') || (*url == '\t'))) url++;
+
+ /*
+ * Process command-line switches to determine the loader stack
+ */
+
+ la->la_loader = NULL;
+ if (cmd_sw_isset(cmd,"-elf")) la->la_loader = "elf";
+ if (cmd_sw_isset(cmd,"-srec")) la->la_loader = "srec";
+ if (cmd_sw_isset(cmd,"-raw")) la->la_loader = "raw";
+ if (cmd_sw_value(cmd,"-loader",&x)) la->la_loader = x;
+
+#if CFG_ZLIB
+ if (cmd_sw_isset(cmd,"-z")) {
+ la->la_flags |= LOADFLG_COMPRESSED;
+ }
+#endif
+
+ /*
+ * Parse the file name into its pieces.
+ */
+
+#if CFG_URLS
+ res = process_url(url,cmd,la);
+ if (res < 0) return res;
+#else
+ res = process_oldstyle(url,cmd,la);
+ if (res < 0) return res;
+#endif
+
+
+ /*
+ * This is used only by "boot" and "load" - to avoid this code
+ * don't include these switches in the command table.
+ */
+
+ if (cmd_sw_value(cmd,"-max",&x)) {
+ la->la_maxsize = atoi(x);
+ }
+
+ if (cmd_sw_value(cmd,"-addr",&x)) {
+ la->la_address = getaddr(x);
+ la->la_flags |= LOADFLG_SPECADDR;
+ }
+
+ if (cmd_sw_isset(cmd,"-noclose")) {
+ la->la_flags |= LOADFLG_NOCLOSE;
+ }
+
+#if 0
+ printf("--- Loader parameters:\n");
+ printf(" Filename = %s\n",la->la_filename);
+ printf(" Filesys = %s\n",la->la_filesys);
+ printf(" Device = %s\n",la->la_device);
+ printf(" Options = %s\n",la->la_options);
+ printf(" Loader = %s\n",la->la_loader);
+ printf(" Flags = %08X\n",la->la_flags);
+ printf(" address = %08X\n",la->la_address);
+ printf(" maxsize = %08X\n",la->la_maxsize);
+ printf(" entrypt = %08X\n",la->la_entrypt);
+#endif
+
+ return 0;
+}
+
+
+
diff --git a/cfe/cfe/ui/url.h b/cfe/cfe/ui/url.h
new file mode 100644
index 0000000..268c7f8
--- /dev/null
+++ b/cfe/cfe/ui/url.h
@@ -0,0 +1,52 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Program and file loading URLs File: url.h
+ *
+ * Functions to process URLs for loading software.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions as
+ * they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. Neither the "Broadcom
+ * Corporation" name nor any trademark or logo of Broadcom
+ * Corporation may be used to endorse or promote products
+ * derived from this software without the prior written
+ * permission of Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+#ifndef _URL_H_
+#define _URL_H_ 1
+
+int ui_process_url(char *URL, ui_cmdline_t *cmd,cfe_loadargs_t *la);
+
+#endif /* _URL_H_ */
diff --git a/cfe/cfe/usb/Makefile b/cfe/cfe/usb/Makefile
new file mode 100644
index 0000000..fa38870
--- /dev/null
+++ b/cfe/cfe/usb/Makefile
@@ -0,0 +1,8 @@
+
+#
+# Makefile for USB stuff
+#
+
+
+ALLOBJS += usbmain.o ohci.o usbd.o usbdevs.o usbhub.o usbdebug.o usbhid.o usbmass.o usbserial.o usbeth.o
+CFLAGS += -DCFG_USB=1
diff --git a/cfe/cfe/usb/README b/cfe/cfe/usb/README
new file mode 100644
index 0000000..28ac9bf
--- /dev/null
+++ b/cfe/cfe/usb/README
@@ -0,0 +1,183 @@
+
+------------------------------------------------------------------------
+This directory contains a basic description of the CFE USB stack,
+its current status and features, and what might be done in the
+future to improve it.
+------------------------------------------------------------------------
+
+Question: A USB stack in CFE? But why?
+
+Answer: Why not? It's not terribly useful on the BCM1250, since we
+ don't expect many of you to use USB in your boards, but there IS
+ a USB host controller on the SWARM (BCM1250 reference design).
+ Besides, CFE is actually being used for other non-SiByte
+ Broadcom chips, and some of those _do_ have USB on them.
+
+------------------------------------------------------------------------
+
+Source Files
+------------
+
+ohci.c OHCI USB Host Controller Driver, tested on a BCM1250
+ with an Opti FireLink PCI USB controller
+
+ohci.h Register definitions for ohci.c
+
+usbchap9.h USB "Chapter 9" definitions (Descriptors, etc.)
+
+usbd.c USB Basic Request and pipe management routines, to
+ manage usb devices, do simple requests on the
+ control pipe, open and manage pipes, etc.
+
+usbd.h Prototypes and data structures for usbd.c
+
+usbdevs.c USB Device Driver list - devices we recognize
+ are listed here - if you add a new USB device,
+ you can add its class or vendor ID entries
+ into the table here.
+
+usbdebug.c Some descriptor dump routines live here.
+
+usbhub.c Class driver for USB hubs. Because hubs are also
+ a major player in device discovery, much of the
+ USB device tree management also lives here.
+
+usbhid.c Class driver for keyboards and mice. Right now
+ not much is done with them except echo characters.
+
+usbmass.c Class driver for USB mass-storage devices. We only
+ support the "bulk-only-no-interrupt" protocol.
+ This driver also includes a top half so that
+ it can be accessed as a CFE mass-storage device.
+
+usbmain.c Top-level interface into CFE. The "usb start"
+ command is instantiated here, as well as a
+ "usb show" command to display attached USB devices.
+
+usbhack.c Main program for the test harness, which lets you
+ develop OHCI code under Linux without hacking on
+ either CFE or the kernel. See the comments in this
+ file for more information.
+
+usbhack.h A dumping ground for CFE definitions not otherwise
+ provided by the standard include files.
+
+usbhack.mk GNU makefile for the test harness
+
+------------------------------------------------------------------------
+
+Overview
+--------
+
+The host controller driver is abstracted through a small set of
+primitives defined in usbd.h - at present only the OHCI driver
+is implemented, but there will eventually be support for the
+ScanLogic SL11H part on the BCM1250CPCI board - this is a simple
+"generic-bus" (non-pci) host controller. I doubt we'll ever
+need EHCI/UHCI, since they are present mostly in Intel chipsets.
+
+All events are polled by this driver. There are two polling functions
+that should be called periodically:
+
+ usb_poll(usbbus_t *bus);
+ usb_daemon(usbbus_t *bus);
+
+The "poll" routine handles interrupts from the devices themselves.
+The "daemon" routine monitors the bus for topology changes and
+instantiates an exploration if something changes. Sometimes "daemon"
+needs to do USB I/O, requiring calls to usb_poll() to get the data
+to go in/out via the controller, hence the two routines. You should
+be careful not to all usb_poll() during polling.
+
+
+Device Drivers
+--------------
+
+USB Device drivers are currently extremely simple: There are
+only two methods that need be exported to the device driver table:
+
+attach() Called when the device is "discovered"
+detach() Called when the device is "removed"
+
+When a device is removed, pending transfer requests will be
+canceled with a "canceled" status.
+
+There is no standard for the top side (user API side) of the
+device driver, that is up to the device class. The bottom half
+should make use of the calls in usbd.c
+
+When a device driver is attached via its attach() method,
+it will be in the "addressed" state according to the USB spec.
+The exploration code takes care of assigning the USB address
+to the device. Devices not otherwise recognized by this code will
+be left in the addressed state without any active configurations.
+
+The descriptors are read by the exploration code and are made
+available to the usb_find_cfg_descr() call - you can use this
+function to obtain the endpoint and interface descriptors for
+your device and then call usb_set_configuration() to activate
+the configuration.
+
+When your detach() method is called, the device should be considered
+already gone, so do not attempt to do any I/O to it. Just clean
+up the mess and return.
+
+
+------------------------------------------------------------------------
+
+What works?
+-----------
+
+* OHCI on a BCM1250 via the Opti Firelink USB controller
+
+* The OHCI root hub emulation
+
+* External hubs, and hubs integrated into other devices like
+ keyboards.
+
+* Interrupt transfers
+
+* Transfers (basic requests) on endpoint 0
+
+* Basic device discovery and removal
+
+* Bulk endpoints and transfers
+
+* Some endpoint stalls are handled.
+
+
+------------------------------------------------------------------------
+
+What doesn't work? What is not implemented?
+--------------------------------------------
+
+* The root hub implementation is really shaky, especially in
+ matters of plug-and-play (device insertion/removal events,
+ etc.) Don't be surprised if removing a device from the
+ root hub causes CFE to freeze.
+
+* There is no error recovery code whatsoever. This kind of goes
+ with the above root hub issue.
+
+* Noncoherent DMA is relatively untested.
+
+* Isochronous endpoints are completely unimplemented (and will probably
+ remain that way)
+
+* Power management (for example, power budget in hubs) is unimplemented.
+ (this should be easy)
+
+* Interrupt endpoints are all on the 10ms endpoint in the interrupt
+ tree (endpoints should be placed at the location to guarantee
+ bandwidth at 'bInterval' ms) - no bandwidth management is being
+ done at the moment, but this is pretty simple.
+
+* The OHCI driver cannot be stopped/unloaded.
+
+
+
+
+
+
+
+
diff --git a/cfe/cfe/usb/ohci.c b/cfe/cfe/usb/ohci.c
new file mode 100644
index 0000000..c002091
--- /dev/null
+++ b/cfe/cfe/usb/ohci.c
@@ -0,0 +1,2126 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * OHCI device driver File: ohci.c
+ *
+ * Open Host Controller Interface low-level routines
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#ifndef _CFE_
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+#include "usbhack.h"
+#define CPUCFG_COHERENT_DMA 1 /* hack runs on a PC, PCs are coherent */
+#else
+#include "lib_types.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "lib_physio.h"
+#include "addrspace.h"
+#include "cpu_config.h" /* for CPUCFG_COHERENT_DMA */
+#endif
+
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "usbchap9.h"
+#include "usbd.h"
+#include "ohci.h"
+
+
+/* *********************************************************************
+ * Macros for dealing with hardware
+ *
+ * This is all yucky stuff that needs to be made more
+ * processor-independent. It's mostly here now to help us with
+ * our test harness.
+ ********************************************************************* */
+
+#if defined(_CFE_) && defined(__MIPSEB)
+#define BSWAP32(x) __swap32(x)
+static inline uint32_t __swap32(uint32_t x)
+{
+ uint32_t y;
+
+ y = ((x & 0xFF) << 24) |
+ ((x & 0xFF00) << 8) |
+ ((x & 0xFF0000) >> 8) |
+ ((x & 0xFF000000) >> 24);
+
+ return y;
+}
+#else
+#define BSWAP32(x) (x)
+#endif
+
+
+#ifndef _CFE_
+extern uint32_t vtop(void *ptr);
+extern void *ptov(uint32_t x);
+#define OHCI_VTOP(ptr) vtop(ptr)
+#define OHCI_PTOV(ptr) ptov(ptr)
+#define OHCI_WRITECSR(softc,x,y) \
+ *((volatile uint32_t *) ((softc)->ohci_regs + ((x)/sizeof(uint32_t)))) = (y)
+#define OHCI_READCSR(softc,x) \
+ *((volatile uint32_t *) ((softc)->ohci_regs + ((x)/sizeof(uint32_t))))
+#else
+#define OHCI_VTOP(ptr) ((uint32_t)PHYSADDR((long)(ptr)))
+
+#if CPUCFG_COHERENT_DMA
+#define OHCI_PTOV(ptr) ((void *)(KERNADDR(ptr)))
+#else
+#define OHCI_PTOV(ptr) ((void *)(UNCADDR(ptr)))
+#endif
+
+#define OHCI_WRITECSR(softc,x,y) \
+ phys_write32(((softc)->ohci_regs + (x)),(y))
+#define OHCI_READCSR(softc,x) \
+ phys_read32(((softc)->ohci_regs + (x)))
+#endif
+
+#if CPUCFG_COHERENT_DMA
+#define OHCI_INVAL_RANGE(s,l)
+#define OHCI_FLUSH_RANGE(s,l)
+#else /* not coherent */
+#define CFE_CACHE_INVAL_RANGE 32 /* XXX belongs in include file */
+#define CFE_CACHE_FLUSH_RANGE 64
+extern void _cfe_flushcache(int,uint8_t *,uint8_t *);
+#define OHCI_INVAL_RANGE(s,l) _cfe_flushcache(CFE_CACHE_INVAL_RANGE,((uint8_t *) (s)),((uint8_t *) (s))+(l))
+#define OHCI_FLUSH_RANGE(s,l) _cfe_flushcache(CFE_CACHE_FLUSH_RANGE,((uint8_t *) (s)),((uint8_t *) (s))+(l))
+#endif
+
+
+/* *********************************************************************
+ * Bit-reverse table - this table consists of the numbers
+ * at its index, listed in reverse. So, the reverse of 0000 0010
+ * is 0100 0000.
+ ********************************************************************* */
+
+const static int ohci_revbits[OHCI_INTTABLE_SIZE] = {
+ 0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c,
+ 0x02, 0x12, 0x0a, 0x1a, 0x06, 0x16, 0x0e, 0x1e,
+ 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d,
+ 0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f
+};
+
+
+/* *********************************************************************
+ * Macros to convert from "hardware" endpoint and transfer
+ * descriptors (ohci_ed_t, ohci_td_t) to "software"
+ * data structures (ohci_transfer_t, ohci_endpoint_t).
+ *
+ * Basically, there are two tables, indexed by the same value
+ * By subtracting the base of one pool from a pointer, we get
+ * the index into the other table.
+ *
+ * We *could* have included the ed and td in the software
+ * data structures, but placing all the hardware stuff in one
+ * pool will make it easier for hardware that does not handle
+ * coherent DMA, since we can be less careful about what we flush
+ * and what we invalidate.
+ ********************************************************************* */
+
+#define ohci_td_from_transfer(softc,transfer) \
+ ((softc)->ohci_hwtdpool + ((transfer) - (softc)->ohci_transfer_pool))
+
+#define ohci_transfer_from_td(softc,td) \
+ ((softc)->ohci_transfer_pool + ((td) - (softc)->ohci_hwtdpool))
+
+#define ohci_ed_from_endpoint(softc,endpoint) \
+ ((softc)->ohci_hwedpool + ((endpoint) - (softc)->ohci_endpoint_pool))
+
+#define ohci_endpoint_from_ed(softc,ed) \
+ ((softc)->ohci_endpoint_pool + ((ed) - (softc)->ohci_hwedpool))
+
+/* *********************************************************************
+ * Forward declarations
+ ********************************************************************* */
+
+static int ohci_roothub_xfer(usbbus_t *bus,usb_ept_t *uept,usbreq_t *ur);
+static void ohci_roothub_statchg(ohci_softc_t *softc);
+extern usb_hcdrv_t ohci_driver;
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+int ohcidebug = 0;
+void ohci_dumprhstat(uint32_t reg);
+void ohci_dumpportstat(int idx,uint32_t reg);
+void ohci_dumptd(ohci_td_t *td);
+void ohci_dumptdchain(ohci_td_t *td);
+void ohci_dumped(ohci_ed_t *ed);
+void ohci_dumpedchain(ohci_ed_t *ed);
+
+
+/* *********************************************************************
+ * Some debug routines
+ ********************************************************************* */
+
+#if 1
+void ohci_dumprhstat(uint32_t reg)
+{
+ printf("HubStatus: %08X ",reg);
+
+ if (reg & M_OHCI_RHSTATUS_LPS) printf("LocalPowerStatus ");
+ if (reg & M_OHCI_RHSTATUS_OCI) printf("OverCurrent ");
+ if (reg & M_OHCI_RHSTATUS_DRWE) printf("DeviceRemoteWakeupEnable ");
+ if (reg & M_OHCI_RHSTATUS_LPSC) printf("LocalPowerStatusChange ");
+ if (reg & M_OHCI_RHSTATUS_OCIC) printf("OverCurrentIndicatorChange ");
+ printf("\n");
+
+}
+
+void ohci_dumpportstat(int idx,uint32_t reg)
+{
+ printf("Port %d: %08X ",idx,reg);
+ if (reg & M_OHCI_RHPORTSTAT_CCS) printf("Connected ");
+ if (reg & M_OHCI_RHPORTSTAT_PES) printf("PortEnabled ");
+ if (reg & M_OHCI_RHPORTSTAT_PSS) printf("PortSuspended ");
+ if (reg & M_OHCI_RHPORTSTAT_POCI) printf("PortOverCurrent ");
+ if (reg & M_OHCI_RHPORTSTAT_PRS) printf("PortReset ");
+ if (reg & M_OHCI_RHPORTSTAT_PPS) printf("PortPowered ");
+ if (reg & M_OHCI_RHPORTSTAT_LSDA) printf("LowSpeed ");
+ if (reg & M_OHCI_RHPORTSTAT_CSC) printf("ConnectStatusChange ");
+ if (reg & M_OHCI_RHPORTSTAT_PESC) printf("PortEnableStatusChange ");
+ if (reg & M_OHCI_RHPORTSTAT_PSSC) printf("PortSuspendStatusChange ");
+ if (reg & M_OHCI_RHPORTSTAT_OCIC) printf("OverCurrentIndicatorChange ");
+ if (reg & M_OHCI_RHPORTSTAT_PRSC) printf("PortResetStatusChange ");
+ printf("\n");
+}
+
+void ohci_dumptd(ohci_td_t *td)
+{
+ uint32_t ctl;
+ static char *pids[4] = {"SETUP","OUT","IN","RSVD"};
+
+ ctl = BSWAP32(td->td_control);
+
+ printf("[%08X] ctl=%08X (DP=%s,DI=%d,T=%d,EC=%d,CC=%d%s) cbp=%08X be=%08X next=%08X\n",
+ OHCI_VTOP(td),
+ ctl,
+ pids[G_OHCI_TD_PID(ctl)],
+ G_OHCI_TD_DI(ctl),
+ G_OHCI_TD_DT(ctl),
+ G_OHCI_TD_EC(ctl),
+ G_OHCI_TD_CC(ctl),
+ (ctl & M_OHCI_TD_SHORTOK) ? ",R" : "",
+ BSWAP32(td->td_cbp),
+ BSWAP32(td->td_be),
+ BSWAP32(td->td_next_td));
+}
+
+void ohci_dumptdchain(ohci_td_t *td)
+{
+ int idx = 0;
+ for (;;) {
+ printf("%d:[%08X] ctl=%08X cbp=%08X be=%08X next=%08X\n",
+ idx,
+ OHCI_VTOP(td),
+ BSWAP32(td->td_control),
+ BSWAP32(td->td_cbp),
+ BSWAP32(td->td_be),
+ BSWAP32(td->td_next_td));
+ if (!td->td_next_td) break;
+ td = (ohci_td_t *) OHCI_PTOV(BSWAP32(td->td_next_td));
+ idx++;
+ }
+}
+
+void ohci_dumped(ohci_ed_t *ed)
+{
+ uint32_t ctl;
+ static char *pids[4] = {"FTD","OUT","IN","FTD"};
+
+ ctl = BSWAP32(ed->ed_control),
+
+ printf("[%08X] Ctl=%08X (MPS=%d%s%s%s,EN=%d,FA=%d,D=%s) Tailp=%08X headp=%08X next=%08X %s\n",
+ OHCI_VTOP(ed),
+ ctl,
+ G_OHCI_ED_MPS(ctl),
+ (ctl & M_OHCI_ED_LOWSPEED) ? ",LS" : "",
+ (ctl & M_OHCI_ED_SKIP) ? ",SKIP" : "",
+ (ctl & M_OHCI_ED_ISOCFMT) ? ",ISOC" : "",
+ G_OHCI_ED_EN(ctl),
+ G_OHCI_ED_FA(ctl),
+ pids[G_OHCI_ED_DIR(ctl)],
+ BSWAP32(ed->ed_tailp),
+ BSWAP32(ed->ed_headp),
+ BSWAP32(ed->ed_next_ed),
+ BSWAP32(ed->ed_headp) & M_OHCI_ED_HALT ? "HALT" : "");
+ if ((ed->ed_headp & M_OHCI_ED_PTRMASK) == 0) return;
+ ohci_dumptdchain(OHCI_PTOV(BSWAP32(ed->ed_headp) & M_OHCI_ED_PTRMASK));
+}
+
+void ohci_dumpedchain(ohci_ed_t *ed)
+{
+ int idx = 0;
+ for (;;) {
+ printf("---\nED#%d -> ",idx);
+ ohci_dumped(ed);
+ if (!ed->ed_next_ed) break;
+ if (idx > 50) break;
+ ed = (ohci_ed_t *) OHCI_PTOV(BSWAP32(ed->ed_next_ed));
+ idx++;
+ }
+}
+
+#endif
+
+
+static void eptstats(ohci_softc_t *softc)
+{
+ int cnt;
+ ohci_endpoint_t *e;
+ cnt = 0;
+
+ e = softc->ohci_endpoint_freelist;
+ while (e) { e = e->ep_next; cnt++; }
+ printf("%d left, %d inuse\n",cnt,OHCI_EDPOOL_SIZE-cnt);
+}
+
+/* *********************************************************************
+ * _ohci_allocept(softc)
+ *
+ * Allocate an endpoint data structure from the pool, and
+ * make it ready for use. The endpoint is NOT attached to
+ * the hardware at this time.
+ *
+ * Input parameters:
+ * softc - our OHCI controller
+ *
+ * Return value:
+ * pointer to endpoint or NULL
+ ********************************************************************* */
+
+static ohci_endpoint_t *_ohci_allocept(ohci_softc_t *softc)
+{
+ ohci_endpoint_t *e;
+ ohci_ed_t *ed;
+
+ if (ohcidebug > 2) {
+ printf("AllocEpt: ");eptstats(softc);
+ }
+
+ e = softc->ohci_endpoint_freelist;
+
+ if (!e) {
+ printf("No endpoints left!\n");
+ return NULL;
+ }
+
+ softc->ohci_endpoint_freelist = e->ep_next;
+
+ ed = ohci_ed_from_endpoint(softc,e);
+
+ ed->ed_control = BSWAP32(M_OHCI_ED_SKIP);
+ ed->ed_tailp = BSWAP32(0);
+ ed->ed_headp = BSWAP32(0);
+ ed->ed_next_ed = BSWAP32(0);
+
+ e->ep_phys = OHCI_VTOP(ed);
+ e->ep_next = NULL;
+
+ return e;
+}
+
+/* *********************************************************************
+ * _ohci_allocxfer(softc)
+ *
+ * Allocate a transfer descriptor. It is prepared for use
+ * but not attached to the hardware.
+ *
+ * Input parameters:
+ * softc - our OHCI controller
+ *
+ * Return value:
+ * transfer descriptor, or NULL
+ ********************************************************************* */
+
+static ohci_transfer_t *_ohci_allocxfer(ohci_softc_t *softc)
+{
+ ohci_transfer_t *t;
+ ohci_td_t *td;
+
+ if (ohcidebug > 2) {
+ int cnt;
+ cnt = 0;
+ t = softc->ohci_transfer_freelist;
+ while (t) { t = t->t_next; cnt++; }
+ printf("AllocXfer: %d left, %d inuse\n",cnt,OHCI_TDPOOL_SIZE-cnt);
+ }
+
+ t = softc->ohci_transfer_freelist;
+
+ if (!t) {
+ printf("No more transfer descriptors!\n");
+ return NULL;
+ }
+
+ softc->ohci_transfer_freelist = t->t_next;
+
+ td = ohci_td_from_transfer(softc,t);
+
+ td->td_control = BSWAP32(0);
+ td->td_cbp = BSWAP32(0);
+ td->td_next_td = BSWAP32(0);
+ td->td_be = BSWAP32(0);
+
+ t->t_ref = NULL;
+ t->t_next = NULL;
+
+ return t;
+}
+
+/* *********************************************************************
+ * _ohci_freeept(softc,e)
+ *
+ * Free an endpoint, returning it to the pool.
+ *
+ * Input parameters:
+ * softc - our OHCI controller
+ * e - endpoint descriptor to return
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void _ohci_freeept(ohci_softc_t *softc,ohci_endpoint_t *e)
+{
+ if (ohcidebug > 2) {
+ int cnt;
+ ohci_endpoint_t *ee;
+ cnt = 0;
+ ee = softc->ohci_endpoint_freelist;
+ while (ee) { ee = ee->ep_next; cnt++; }
+ printf("FreeEpt[%p]: %d left, %d inuse\n",e,cnt,OHCI_EDPOOL_SIZE-cnt);
+ }
+
+ e->ep_next = softc->ohci_endpoint_freelist;
+ softc->ohci_endpoint_freelist = e;
+}
+
+/* *********************************************************************
+ * _ohci_freexfer(softc,t)
+ *
+ * Free a transfer descriptor, returning it to the pool.
+ *
+ * Input parameters:
+ * softc - our OHCI controller
+ * t - transfer descriptor to return
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void _ohci_freexfer(ohci_softc_t *softc,ohci_transfer_t *t)
+{
+ t->t_next = softc->ohci_transfer_freelist;
+ softc->ohci_transfer_freelist = t;
+}
+
+/* *********************************************************************
+ * _ohci_initpools(softc)
+ *
+ * Allocate and initialize the various pools of things that
+ * we use in the OHCI driver. We do this by allocating some
+ * big chunks from the heap and carving them up.
+ *
+ * Input parameters:
+ * softc - our OHCI controller
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int _ohci_initpools(ohci_softc_t *softc)
+{
+ int idx;
+
+ /*
+ * Do the transfer descriptor pool
+ */
+
+ softc->ohci_transfer_pool = KMALLOC(OHCI_TDPOOL_SIZE*sizeof(ohci_transfer_t),0);
+ softc->ohci_hwtdpool = KMALLOC(OHCI_TDPOOL_SIZE*sizeof(ohci_td_t),OHCI_TD_ALIGN);
+
+ /*
+ * In the case of noncoherent DMA, make these uncached addresses.
+ * This way all our descriptors will be uncached. Makes life easier, as we
+ * do not need to worry about flushing descriptors, etc.
+ */
+
+#if (!CPUCFG_COHERENT_DMA)
+ softc->ohci_hwtdpool = (void *) UNCADDR(PHYSADDR((uint32_t)(softc->ohci_hwtdpool)));
+#endif
+
+ if (!softc->ohci_transfer_pool || !softc->ohci_hwtdpool) {
+ printf("Could not allocate transfer descriptors\n");
+ return -1;
+ }
+
+ softc->ohci_transfer_freelist = NULL;
+
+ for (idx = 0; idx < OHCI_TDPOOL_SIZE; idx++) {
+ _ohci_freexfer(softc,softc->ohci_transfer_pool+idx);
+ }
+
+ /*
+ * Do the endpoint descriptor pool
+ */
+
+ softc->ohci_endpoint_pool = KMALLOC(OHCI_EDPOOL_SIZE*sizeof(ohci_endpoint_t),0);
+
+ softc->ohci_hwedpool = KMALLOC(OHCI_EDPOOL_SIZE*sizeof(ohci_ed_t),OHCI_ED_ALIGN);
+
+#if (!CPUCFG_COHERENT_DMA)
+ softc->ohci_hwedpool = (void *) UNCADDR(PHYSADDR((uint32_t)(softc->ohci_hwedpool)));
+#endif
+
+ if (!softc->ohci_endpoint_pool || !softc->ohci_hwedpool) {
+ printf("Could not allocate transfer descriptors\n");
+ return -1;
+ }
+
+ softc->ohci_endpoint_freelist = NULL;
+
+ for (idx = 0; idx < OHCI_EDPOOL_SIZE; idx++) {
+ _ohci_freeept(softc,softc->ohci_endpoint_pool+idx);
+ }
+
+ /*
+ * Finally the host communications area
+ */
+
+ softc->ohci_hcca = KMALLOC(sizeof(ohci_hcca_t),sizeof(ohci_hcca_t));
+
+#if (!CPUCFG_COHERENT_DMA)
+ softc->ohci_hcca = (void *) UNCADDR(PHYSADDR((uint32_t)(softc->ohci_hcca)));
+#endif
+
+ memset(softc->ohci_hcca,0,sizeof(ohci_hcca_t));
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * ohci_start(bus)
+ *
+ * Start the OHCI controller. After this routine is called,
+ * the hardware will be operational and ready to accept
+ * descriptors and interrupt calls.
+ *
+ * Input parameters:
+ * bus - bus structure, from ohci_create
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int ohci_start(usbbus_t *bus)
+{
+ ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc;
+ uint32_t frameint;
+ uint32_t reg;
+ int idx;
+
+ /*
+ * Force a reset to the controller, followed by a short delay
+ */
+
+ OHCI_WRITECSR(softc,R_OHCI_CONTROL,V_OHCI_CONTROL_HCFS(K_OHCI_HCFS_RESET));
+ usb_delay_ms(bus,OHCI_RESET_DELAY);
+
+ /* Host controller state is now "RESET" */
+
+ /*
+ * We need the frame interval later, so get a copy of it now.
+ */
+ frameint = G_OHCI_FMINTERVAL_FI(OHCI_READCSR(softc,R_OHCI_FMINTERVAL));
+
+ /*
+ * Reset the host controller. When you set the HCR bit
+ * if self-clears when the reset is complete.
+ */
+
+ OHCI_WRITECSR(softc,R_OHCI_CMDSTATUS,M_OHCI_CMDSTATUS_HCR);
+ for (idx = 0; idx < 10000; idx++) {
+ if (!(OHCI_READCSR(softc,R_OHCI_CMDSTATUS) & M_OHCI_CMDSTATUS_HCR)) break;
+ }
+
+ if (OHCI_READCSR(softc,R_OHCI_CMDSTATUS) & M_OHCI_CMDSTATUS_HCR) {
+ /* controller never came out of reset */
+ return -1;
+ }
+
+ /*
+ * Host controller state is now "SUSPEND". We must exit
+ * from this state within 2ms. (5.1.1.4)
+ *
+ * Set up pointers to data structures.
+ */
+
+ OHCI_WRITECSR(softc,R_OHCI_HCCA,OHCI_VTOP(softc->ohci_hcca));
+ OHCI_WRITECSR(softc,R_OHCI_CONTROLHEADED,softc->ohci_ctl_list->ep_phys);
+ OHCI_WRITECSR(softc,R_OHCI_BULKHEADED,softc->ohci_bulk_list->ep_phys);
+
+ /*
+ * Our driver is polled, turn off interrupts
+ */
+
+ OHCI_WRITECSR(softc,R_OHCI_INTDISABLE,M_OHCI_INT_ALL);
+
+ /*
+ * Set up the control register.
+ */
+
+ reg = OHCI_READCSR(softc,R_OHCI_CONTROL);
+
+ reg = M_OHCI_CONTROL_PLE | M_OHCI_CONTROL_CLE | M_OHCI_CONTROL_BLE |
+ M_OHCI_CONTROL_IE |
+ V_OHCI_CONTROL_CBSR(K_OHCI_CBSR_41) |
+ V_OHCI_CONTROL_HCFS(K_OHCI_HCFS_OPERATIONAL);
+
+ OHCI_WRITECSR(softc,R_OHCI_CONTROL,reg);
+
+
+ /*
+ * controller state is now OPERATIONAL
+ */
+
+ reg = OHCI_READCSR(softc,R_OHCI_FMINTERVAL);
+ reg &= M_OHCI_FMINTERVAL_FIT;
+ reg ^= M_OHCI_FMINTERVAL_FIT;
+ reg |= V_OHCI_FMINTERVAL_FSMPS(OHCI_CALC_FSMPS(frameint)) |
+ V_OHCI_FMINTERVAL_FI(frameint);
+ OHCI_WRITECSR(softc,R_OHCI_FMINTERVAL,reg);
+
+ reg = frameint * 9 / 10; /* calculate 90% */
+ OHCI_WRITECSR(softc,R_OHCI_PERIODICSTART,reg);
+
+ usb_delay_ms(softc->ohci_bus,10);
+
+ /*
+ * Remember how many ports we have
+ */
+
+ reg = OHCI_READCSR(softc,R_OHCI_RHDSCRA);
+ softc->ohci_ndp = G_OHCI_RHDSCRA_NDP(reg);
+
+
+ /*
+ * Enable port power
+ */
+
+ OHCI_WRITECSR(softc,R_OHCI_RHSTATUS,M_OHCI_RHSTATUS_LPSC);
+ usb_delay_ms(softc->ohci_bus,10);
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * _ohci_setupepts(softc)
+ *
+ * Set up the endpoint tree, as described in the OHCI manual.
+ * Basically the hardware knows how to scan lists of lists,
+ * so we build a tree where each level is pointed to by two
+ * parent nodes. We can choose our scanning rate by attaching
+ * endpoints anywhere within this tree.
+ *
+ * Input parameters:
+ * softc - our OHCI controller
+ *
+ * Return value:
+ * 0 if ok
+ * else error (out of descriptors)
+ ********************************************************************* */
+
+static int _ohci_setupepts(ohci_softc_t *softc)
+{
+ int idx;
+ ohci_endpoint_t *e;
+ ohci_ed_t *ed;
+ ohci_endpoint_t *child;
+
+ /*
+ * Set up the list heads for the isochronous, control,
+ * and bulk transfer lists. They don't get the same "tree"
+ * treatment that the interrupt devices get.
+ *
+ * For the purposes of CFE, it's probably not necessary
+ * to be this fancy. The only device we're planning to
+ * talk to is the keyboard and some hubs, which should
+ * have pretty minimal requirements. It's conceivable
+ * that this firmware may find a new home in other
+ * devices, so we'll meet halfway and do some things
+ * "fancy."
+ */
+
+ softc->ohci_isoc_list = _ohci_allocept(softc);
+ softc->ohci_ctl_list = _ohci_allocept(softc);
+ softc->ohci_bulk_list = _ohci_allocept(softc);
+
+ /*
+ * Set up a tree of empty endpoint descriptors. This is
+ * tree is scanned by the hardware from the leaves up to
+ * the root. Once a millisecond, the hardware picks the
+ * next leaf and starts scanning descriptors looking
+ * for something to do. It traverses all of the endpoints
+ * along the way until it gets to the root.
+ *
+ * The idea here is if you put a transfer descriptor on the
+ * root node, the hardware will see it every millisecond,
+ * since the root will be examined each time. If you
+ * put the TD on the leaf, it will be 1/32 millisecond.
+ * The tree therefore is six levels deep.
+ */
+
+ for (idx = 0; idx < OHCI_INTTREE_SIZE; idx++) {
+ e = _ohci_allocept(softc); /* allocated with sKip bit set */
+ softc->ohci_edtable[idx] = e;
+ child = (idx == 0) ? softc->ohci_isoc_list : softc->ohci_edtable[(idx-1)/2];
+ ed = ohci_ed_from_endpoint(softc,e);
+ ed->ed_next_ed = BSWAP32(child->ep_phys);
+ e->ep_next = child;
+ }
+
+ /*
+ * We maintain both physical and virtual copies of the interrupt
+ * table (leaves of the tree).
+ */
+
+ for (idx = 0; idx < OHCI_INTTABLE_SIZE; idx++) {
+ child = softc->ohci_edtable[OHCI_INTTREE_SIZE-OHCI_INTTABLE_SIZE+idx];
+ softc->ohci_inttable[ohci_revbits[idx]] = child;
+ softc->ohci_hcca->hcca_inttable[ohci_revbits[idx]] = BSWAP32(child->ep_phys);
+ }
+
+ /*
+ * Okay, at this point the tree is built.
+ */
+ return 0;
+}
+
+/* *********************************************************************
+ * ohci_stop(bus)
+ *
+ * Stop the OHCI hardware.
+ *
+ * Input parameters:
+ * bus - our bus structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void ohci_stop(usbbus_t *bus)
+{
+ ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc;
+
+ OHCI_WRITECSR(softc,R_OHCI_CONTROL,V_OHCI_CONTROL_HCFS(K_OHCI_HCFS_RESET));
+}
+
+
+/* *********************************************************************
+ * _ohci_queueept(softc,queue,e)
+ *
+ * Add an endpoint to a list of endpoints. This routine
+ * does things in a particular way according to the OHCI
+ * spec so we can add endpoints while the hardware is running.
+ *
+ * Input parameters:
+ * queue - endpoint descriptor for head of queue
+ * e - endpoint to add to queue
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void _ohci_queueept(ohci_softc_t *softc,ohci_endpoint_t *queue,ohci_endpoint_t *newept)
+{
+ ohci_ed_t *qed;
+ ohci_ed_t *newed;
+
+ qed = ohci_ed_from_endpoint(softc,queue);
+ newed = ohci_ed_from_endpoint(softc,newept);
+
+ newept->ep_next = queue->ep_next;
+ newed->ed_next_ed = qed->ed_next_ed;
+
+ queue->ep_next = newept;
+ qed->ed_next_ed = BSWAP32(newept->ep_phys);
+
+ if (ohcidebug > 1) ohci_dumped(newed);
+
+}
+
+/* *********************************************************************
+ * _ohci_deqept(queue,e)
+ *
+ * Remove and endpoint from the list of endpoints. This
+ * routine does things in a particular way according to
+ * the OHCI specification, since we are operating on
+ * a running list.
+ *
+ * Input parameters:
+ * queue - base of queue to look for endpoint on
+ * e - endpoint to remove
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void _ohci_deqept(ohci_softc_t *softc,ohci_endpoint_t *queue,ohci_endpoint_t *e)
+{
+ ohci_endpoint_t *cur;
+ ohci_ed_t *cured;
+ ohci_ed_t *ed;
+
+ cur = queue;
+
+ while (cur && (cur->ep_next != e)) cur = cur->ep_next;
+
+ if (cur == NULL) {
+ printf("Could not remove EP %08X: not on the list!\n",(uint32_t) (intptr_t)e);
+ return;
+ }
+
+ /*
+ * Remove from our regular list
+ */
+
+ cur->ep_next = e->ep_next;
+
+ /*
+ * now remove from the hardware's list
+ */
+
+ cured = ohci_ed_from_endpoint(softc,cur);
+ ed = ohci_ed_from_endpoint(softc,e);
+
+ cured->ed_next_ed = ed->ed_next_ed;
+}
+
+
+/* *********************************************************************
+ * ohci_intr_procdoneq(softc)
+ *
+ * Process the "done" queue for this ohci controller. As
+ * descriptors are retired, the hardware links them to the
+ * "done" queue so we can examine the results.
+ *
+ * Input parameters:
+ * softc - our OHCI controller
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void ohci_intr_procdoneq(ohci_softc_t *softc)
+{
+ uint32_t doneq;
+ ohci_transfer_t *transfer;
+ ohci_td_t *td;
+ int val;
+ usbreq_t *ur;
+
+ /*
+ * Get the head of the queue
+ */
+
+ doneq = softc->ohci_hcca->hcca_donehead;
+ doneq = BSWAP32(doneq);
+
+ td = (ohci_td_t *) OHCI_PTOV(doneq);
+ transfer = ohci_transfer_from_td(softc,td);
+
+ /*
+ * Process all elements from the queue
+ */
+
+ while (doneq) {
+
+ ohci_ed_t *ed;
+ ohci_endpoint_t *ept;
+ usbreq_t *xur = transfer->t_ref;
+
+ if (ohcidebug > 1) {
+ if (xur) {
+ ept = (ohci_endpoint_t *) xur->ur_pipe->up_hwendpoint;
+ ed = ohci_ed_from_endpoint(softc,ept);
+// printf("ProcDoneQ:ED [%08X] -> ",ept->ep_phys);
+// ohci_dumped(ed);
+ }
+ }
+
+ /*
+ * Get the pointer to next one before freeing this one
+ */
+
+ if (ohcidebug > 1) {
+ ur = transfer->t_ref;
+ printf("Done(%d): ",ur ? ur->ur_tdcount : -1);
+ ohci_dumptd(td);
+ }
+
+ doneq = BSWAP32(td->td_next_td);
+
+ val = G_OHCI_TD_CC(BSWAP32(td->td_control));
+
+ if (val != 0) printf("[Transfer error: %d]\n",val);
+
+ /*
+ * See if it's time to call the callback.
+ */
+ ur = transfer->t_ref;
+ if (ur) {
+ ur->ur_status = val;
+ ur->ur_tdcount--;
+ if (BSWAP32(td->td_cbp) == 0) {
+ ur->ur_xferred += transfer->t_length;
+ }
+ else {
+ ur->ur_xferred += transfer->t_length -
+ (BSWAP32(td->td_be) - BSWAP32(td->td_cbp) + 1);
+ }
+ if (ur->ur_tdcount == 0) {
+ /* Noncoherent DMA: need to invalidate, since data is in phys mem */
+ OHCI_INVAL_RANGE(ur->ur_buffer,ur->ur_xferred);
+ usb_complete_request(ur,val);
+ }
+ }
+
+
+ /*
+ * Free up the request
+ */
+ _ohci_freexfer(softc,transfer);
+
+
+ /*
+ * Advance to the next request.
+ */
+
+ td = (ohci_td_t *) OHCI_PTOV(doneq);
+ transfer = ohci_transfer_from_td(softc,td);
+ }
+
+}
+
+/* *********************************************************************
+ * ohci_intr(bus)
+ *
+ * Process pending interrupts for the OHCI controller.
+ *
+ * Input parameters:
+ * bus - our bus structure
+ *
+ * Return value:
+ * 0 if we did nothing
+ * nonzero if we did something.
+ ********************************************************************* */
+
+static int ohci_intr(usbbus_t *bus)
+{
+ uint32_t reg;
+ ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc;
+
+ /*
+ * Read the interrupt status register.
+ */
+
+ reg = OHCI_READCSR(softc,R_OHCI_INTSTATUS);
+
+ /*
+ * Don't bother doing anything if nothing happened.
+ */
+ if (reg == 0) {
+ return 0;
+ }
+
+ /* Scheduling Overruns */
+ if (reg & M_OHCI_INT_SO) {
+ printf("SchedOverrun\n");
+ }
+
+ /* Done Queue */
+ if (reg & M_OHCI_INT_WDH) {
+ /* printf("DoneQueue\n"); */
+ ohci_intr_procdoneq(softc);
+ }
+
+ /* Start of Frame */
+ if (reg & M_OHCI_INT_SF) {
+ /* don't be noisy about this */
+ }
+
+ /* Resume Detect */
+ if (reg & M_OHCI_INT_RD) {
+ printf("ResumeDetect\n");
+ }
+
+ /* Unrecoverable errors */
+ if (reg & M_OHCI_INT_UE) {
+ printf("UnrecoverableError\n");
+ }
+
+ /* Frame number overflow */
+ if (reg & M_OHCI_INT_FNO) {
+ /*printf("FrameNumberOverflow\n"); */
+ }
+
+ /* Root Hub Status Change */
+ if ((reg & ~softc->ohci_intdisable) & M_OHCI_INT_RHSC) {
+ uint32_t reg;
+ if (ohcidebug > 0) {
+ printf("RootHubStatusChange: ");
+ reg = OHCI_READCSR(softc,R_OHCI_RHSTATUS);
+ ohci_dumprhstat(reg);
+ reg = OHCI_READCSR(softc,R_OHCI_RHPORTSTATUS(1));
+ ohci_dumpportstat(1,reg);
+ reg = OHCI_READCSR(softc,R_OHCI_RHPORTSTATUS(2));
+ ohci_dumpportstat(2,reg);
+ }
+ ohci_roothub_statchg(softc);
+ }
+
+ /* Ownership Change */
+ if (reg & M_OHCI_INT_OC) {
+ printf("OwnershipChange\n");
+ }
+
+ /*
+ * Write the value back to the interrupt
+ * register to clear the bits that were set.
+ */
+
+ OHCI_WRITECSR(softc,R_OHCI_INTSTATUS,reg);
+
+ return 1;
+}
+
+
+/* *********************************************************************
+ * ohci_delete(bus)
+ *
+ * Remove an OHCI bus structure and all resources allocated to
+ * it (used when shutting down USB)
+ *
+ * Input parameters:
+ * bus - our USB bus structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void ohci_delete(usbbus_t *bus)
+{
+ // xxx fill in later.
+}
+
+
+/* *********************************************************************
+ * ohci_create(addr)
+ *
+ * Create a USB bus structure and associate it with our OHCI
+ * controller device.
+ *
+ * Input parameters:
+ * addr - physical address of controller
+ *
+ * Return value:
+ * usbbus structure pointer
+ ********************************************************************* */
+
+static usbbus_t *ohci_create(physaddr_t addr)
+{
+ int res;
+ ohci_softc_t *softc;
+ usbbus_t *bus;
+
+ softc = KMALLOC(sizeof(ohci_softc_t),0);
+ if (!softc) return NULL;
+
+ bus = KMALLOC(sizeof(usbbus_t),0);
+ if (!bus) return NULL;
+
+ memset(softc,0,sizeof(ohci_softc_t));
+ memset(bus,0,sizeof(usbbus_t));
+
+ bus->ub_hwsoftc = (usb_hc_t *) softc;
+ bus->ub_hwdisp = &ohci_driver;
+
+ q_init(&(softc->ohci_rh_intrq));
+
+#ifdef _CFE_
+ softc->ohci_regs = addr;
+#else
+ softc->ohci_regs = (volatile uint32_t *) addr;
+#endif
+
+ softc->ohci_rh_newaddr = -1;
+ softc->ohci_bus = bus;
+
+ if ((res = _ohci_initpools(softc)) != 0) goto error;
+ if ((res = _ohci_setupepts(softc)) != 0) goto error;
+
+ OHCI_WRITECSR(softc,R_OHCI_CONTROL,V_OHCI_CONTROL_HCFS(K_OHCI_HCFS_RESET));
+
+ return bus;
+
+error:
+ KFREE(softc);
+ return NULL;
+}
+
+
+/* *********************************************************************
+ * ohci_ept_create(bus,usbaddr,eptnum,mps,flags)
+ *
+ * Create a hardware endpoint structure and attach it to
+ * the hardware's endpoint list. The hardware manages lists
+ * of queues, and this routine adds a new queue to the appropriate
+ * list of queues for the endpoint in question. It roughly
+ * corresponds to the information in the OHCI specification.
+ *
+ * Input parameters:
+ * bus - the USB bus we're dealing with
+ * usbaddr - USB address (0 means default address)
+ * eptnum - the endpoint number
+ * mps - the packet size for this endpoint
+ * flags - various flags to control endpoint creation
+ *
+ * Return value:
+ * endpoint structure poihter, or NULL
+ ********************************************************************* */
+
+static usb_ept_t *ohci_ept_create(usbbus_t *bus,
+ int usbaddr,
+ int eptnum,
+ int mps,
+ int flags)
+{
+ uint32_t eptflags;
+ ohci_endpoint_t *ept;
+ ohci_ed_t *ed;
+ ohci_transfer_t *tailtransfer;
+ ohci_td_t *tailtd;
+ ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc;
+
+ ept = _ohci_allocept(softc);
+ ed = ohci_ed_from_endpoint(softc,ept);
+
+ tailtransfer = _ohci_allocxfer(softc);
+ tailtd = ohci_td_from_transfer(softc,tailtransfer);
+
+ /*
+ * Set up functional address, endpoint number, and packet size
+ */
+
+ eptflags = V_OHCI_ED_FA(usbaddr) |
+ V_OHCI_ED_EN(eptnum) |
+ V_OHCI_ED_MPS(mps) |
+ 0;
+
+ /*
+ * Set up the endpoint type based on the flags
+ * passed to us
+ */
+
+ if (flags & UP_TYPE_IN) {
+ eptflags |= V_OHCI_ED_DIR(K_OHCI_ED_DIR_IN);
+ }
+ else if (flags & UP_TYPE_OUT) {
+ eptflags |= V_OHCI_ED_DIR(K_OHCI_ED_DIR_OUT);
+ }
+ else {
+ eptflags |= V_OHCI_ED_DIR(K_OHCI_ED_DIR_FROMTD);
+ }
+
+ /*
+ * Don't forget about lowspeed devices.
+ */
+
+ if (flags & UP_TYPE_LOWSPEED) {
+ eptflags |= M_OHCI_ED_LOWSPEED;
+ }
+
+ if (ohcidebug > 0) {
+ printf("Create endpoint %d addr %d flags %08X mps %d\n",
+ eptnum,usbaddr,eptflags,mps);
+ }
+
+ /*
+ * Transfer this info into the endpoint descriptor.
+ * No need to flush the cache here, it'll get done when
+ * we add to the hardware list.
+ */
+
+ ed->ed_control = BSWAP32(eptflags);
+ ed->ed_tailp = BSWAP32(OHCI_VTOP(tailtd));
+ ed->ed_headp = BSWAP32(OHCI_VTOP(tailtd));
+ ept->ep_flags = flags;
+ ept->ep_mps = mps;
+ ept->ep_num = eptnum;
+
+ /*
+ * Put it on the right queue
+ */
+
+ if (flags & UP_TYPE_CONTROL) {
+ _ohci_queueept(softc,softc->ohci_ctl_list,ept);
+ }
+ else if (flags & UP_TYPE_BULK) {
+ _ohci_queueept(softc,softc->ohci_bulk_list,ept);
+ }
+ else if (flags & UP_TYPE_INTR) {
+ /* XXX Choose place in inttable properly. */
+ _ohci_queueept(softc,softc->ohci_inttable[0],ept);
+ }
+
+ return (usb_ept_t *) ept;
+}
+
+/* *********************************************************************
+ * ohci_ept_setaddr(bus,ept,usbaddr)
+ *
+ * Change the functional address for a USB endpoint. We do this
+ * when we switch the device's state from DEFAULT to ADDRESSED
+ * and we've already got the default pipe open. This
+ * routine mucks with the descriptor and changes its address
+ * bits.
+ *
+ * Input parameters:
+ * bus - usb bus structure
+ * ept - an open endpoint descriptor
+ * usbaddr - new address for this endpoint
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void ohci_ept_setaddr(usbbus_t *bus,usb_ept_t *uept,int usbaddr)
+{
+ uint32_t eptflags;
+ ohci_endpoint_t *ept = (ohci_endpoint_t *) uept;
+ ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc;
+ ohci_ed_t *ed = ohci_ed_from_endpoint(softc,ept);
+
+ eptflags = BSWAP32(ed->ed_control);
+ eptflags &= ~M_OHCI_ED_FA;
+ eptflags |= V_OHCI_ED_FA(usbaddr);
+ ed->ed_control = BSWAP32(eptflags);
+}
+
+
+/* *********************************************************************
+ * ohci_ept_setmps(bus,ept,mps)
+ *
+ * Set the maximum packet size of this endpoint. This is
+ * normally used during the processing of endpoint 0 (default
+ * pipe) after we find out how big ep0's packets can be.
+ *
+ * Input parameters:
+ * bus - our USB bus structure
+ * ept - endpoint structure
+ * mps - new packet size
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void ohci_ept_setmps(usbbus_t *bus,usb_ept_t *uept,int mps)
+{
+ uint32_t eptflags;
+ ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc;
+ ohci_endpoint_t *ept = (ohci_endpoint_t *) uept;
+ ohci_ed_t *ed = ohci_ed_from_endpoint(softc,ept);
+
+ eptflags = BSWAP32(ed->ed_control);
+ eptflags &= ~M_OHCI_ED_MPS;
+ eptflags |= V_OHCI_ED_MPS(mps);
+ ed->ed_control = BSWAP32(eptflags);
+ ept->ep_mps = mps;
+
+}
+
+/* *********************************************************************
+ * ohci_ept_cleartoggle(bus,ept,mps)
+ *
+ * Clear the data toggle for the specified endpoint.
+ *
+ * Input parameters:
+ * bus - our USB bus structure
+ * ept - endpoint structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void ohci_ept_cleartoggle(usbbus_t *bus,usb_ept_t *uept)
+{
+ uint32_t eptflags;
+ ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc;
+ ohci_endpoint_t *ept = (ohci_endpoint_t *) uept;
+ ohci_ed_t *ed = ohci_ed_from_endpoint(softc,ept);
+
+ eptflags = BSWAP32(ed->ed_headp);
+ eptflags &= ~(M_OHCI_ED_HALT | M_OHCI_ED_TOGGLECARRY);
+ ed->ed_headp = BSWAP32(eptflags);
+
+ OHCI_WRITECSR(softc,R_OHCI_CMDSTATUS,M_OHCI_CMDSTATUS_CLF);
+}
+
+/* *********************************************************************
+ * ohci_ept_delete(bus,ept)
+ *
+ * Deletes an endpoint from the OHCI controller. This
+ * routine also completes pending transfers for the
+ * endpoint and gets rid of the hardware ept (queue base).
+ *
+ * Input parameters:
+ * bus - ohci bus structure
+ * ept - endpoint to remove
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void ohci_ept_delete(usbbus_t *bus,usb_ept_t *uept)
+{
+ ohci_endpoint_t *queue;
+ ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc;
+ ohci_endpoint_t *ept = (ohci_endpoint_t *) uept;
+ ohci_ed_t *ed = ohci_ed_from_endpoint(softc,ept);
+ uint32_t framenum;
+ uint32_t tdphys;
+ usbreq_t *ur;
+ ohci_td_t *td;
+ ohci_transfer_t *transfer;
+
+ if (ept->ep_flags & UP_TYPE_CONTROL) {
+ queue = softc->ohci_ctl_list;
+ }
+ else if (ept->ep_flags & UP_TYPE_BULK) {
+ queue = softc->ohci_bulk_list;
+ }
+ else if (ept->ep_flags & UP_TYPE_INTR) {
+ queue = softc->ohci_inttable[0];
+ }
+ else {
+ printf("Invalid endpoint\n");
+ return;
+ }
+
+
+ /*
+ * Set the SKIP bit on the endpoint and
+ * wait for two SOFs to guarantee that we're
+ * not processing this ED anymore.
+ */
+
+ ((volatile uint32_t) ed->ed_control) |= BSWAP32(M_OHCI_ED_SKIP);
+
+ framenum = OHCI_READCSR(softc,R_OHCI_FMNUMBER) & 0xFFFF;
+ while ((OHCI_READCSR(softc,R_OHCI_FMNUMBER) & 0xFFFF) == framenum) ; /* NULL LOOP */
+
+ framenum = OHCI_READCSR(softc,R_OHCI_FMNUMBER) & 0xFFFF;
+ while ((OHCI_READCSR(softc,R_OHCI_FMNUMBER) & 0xFFFF) == framenum) ; /* NULL LOOP */
+
+ /*
+ * Remove endpoint from queue
+ */
+
+ _ohci_deqept(softc,queue,ept);
+
+ /*
+ * Free/complete the TDs on the queue
+ */
+
+ tdphys = BSWAP32(ed->ed_headp) & M_OHCI_ED_PTRMASK;
+
+ while (tdphys != BSWAP32(ed->ed_tailp)) {
+ td = (ohci_td_t *) OHCI_PTOV(tdphys);
+ tdphys = BSWAP32(td->td_next_td);
+ transfer = ohci_transfer_from_td(softc,td);
+
+ ur = transfer->t_ref;
+ if (ur) {
+ ur->ur_status = K_OHCI_CC_CANCELLED;
+ ur->ur_tdcount--;
+ if (ur->ur_tdcount == 0) {
+ if (ohcidebug > 0) printf("Completing request due to closed pipe: %p\n",ur);
+ usb_complete_request(ur,K_OHCI_CC_CANCELLED);
+ /* XXX it is expected that the callee will free the usbreq. */
+ }
+ }
+
+ _ohci_freexfer(softc,transfer);
+ }
+
+ /*
+ * tdphys now points at the tail TD. Just free it.
+ */
+
+ td = (ohci_td_t *) OHCI_PTOV(tdphys);
+ _ohci_freexfer(softc,ohci_transfer_from_td(softc,td));
+
+ /*
+ * Return endpoint to free pool
+ */
+
+ _ohci_freeept(softc,ept);
+}
+
+
+
+/* *********************************************************************
+ * ohci_xfer(bus,ept,ur)
+ *
+ * Queue a transfer for the specified endpoint. Depending on
+ * the transfer type, the transfer may go on one of many queues.
+ * When the transfer completes, a callback will be called.
+ *
+ * Input parameters:
+ * bus - bus structure
+ * ept - endpoint descriptor
+ * ur - request (includes pointer to user buffer)
+ *
+ * Return value:
+ * 0 if ok
+ * else error
+ ********************************************************************* */
+
+static int ohci_xfer(usbbus_t *bus,usb_ept_t *uept,usbreq_t *ur)
+{
+ ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc;
+ ohci_endpoint_t *ept = (ohci_endpoint_t *) uept;
+ ohci_ed_t *ed = ohci_ed_from_endpoint(softc,ept);
+ ohci_transfer_t *newtailtransfer = 0;
+ ohci_td_t *newtailtd = NULL;
+ ohci_transfer_t *curtransfer;
+ ohci_td_t *curtd;
+ uint8_t *ptr;
+ int len;
+ int amtcopy;
+ int pktlen;
+ uint32_t tdcontrol = 0;
+
+ /*
+ * If the destination USB address matches
+ * the address of the root hub, shunt the request
+ * over to our root hub emulation.
+ */
+
+ if (ur->ur_dev->ud_address == softc->ohci_rh_addr) {
+ return ohci_roothub_xfer(bus,uept,ur);
+ }
+
+ /*
+ * Set up the TD flags based on the
+ * request type.
+ */
+
+// pktlen = ept->ep_mps;
+ pktlen = OHCI_TD_MAX_DATA - 16;
+
+ if (ur->ur_flags & UR_FLAG_SETUP) {
+ tdcontrol = V_OHCI_TD_PID(K_OHCI_TD_SETUP) |
+ V_OHCI_TD_DT(K_OHCI_TD_DT_DATA0) |
+ V_OHCI_TD_CC(K_OHCI_CC_NOTACCESSED) |
+ V_OHCI_TD_DI(1);
+ }
+ else if (ur->ur_flags & UR_FLAG_IN) {
+ tdcontrol = V_OHCI_TD_PID(K_OHCI_TD_IN) |
+ V_OHCI_TD_DT(K_OHCI_TD_DT_TCARRY) |
+ V_OHCI_TD_CC(K_OHCI_CC_NOTACCESSED) |
+ V_OHCI_TD_DI(1);
+ }
+ else if (ur->ur_flags & UR_FLAG_OUT) {
+ tdcontrol = V_OHCI_TD_PID(K_OHCI_TD_OUT) |
+ V_OHCI_TD_DT(K_OHCI_TD_DT_TCARRY) |
+ V_OHCI_TD_CC(K_OHCI_CC_NOTACCESSED) |
+ V_OHCI_TD_DI(1);
+ }
+ else if (ur->ur_flags & UR_FLAG_STATUS_OUT) {
+ tdcontrol = V_OHCI_TD_PID(K_OHCI_TD_OUT) |
+ V_OHCI_TD_DT(K_OHCI_TD_DT_DATA1) |
+ V_OHCI_TD_CC(K_OHCI_CC_NOTACCESSED) |
+ V_OHCI_TD_DI(1);
+ }
+ else if (ur->ur_flags & UR_FLAG_STATUS_IN) {
+ tdcontrol = V_OHCI_TD_PID(K_OHCI_TD_IN) |
+ V_OHCI_TD_DT(K_OHCI_TD_DT_DATA1) |
+ V_OHCI_TD_CC(K_OHCI_CC_NOTACCESSED) |
+ V_OHCI_TD_DI(1);
+ }
+ else {
+ printf("Shouldn't happen!\n");
+ }
+
+ if (ur->ur_flags & UR_FLAG_SHORTOK) {
+ tdcontrol |= M_OHCI_TD_SHORTOK;
+ }
+
+
+ ptr = ur->ur_buffer;
+ len = ur->ur_length;
+ ur->ur_tdcount = 0;
+
+ if (ohcidebug > 1) {
+ printf(">> Queueing xfer addr %d pipe %d ED %08X ptr %016llX length %d\n",
+ ur->ur_dev->ud_address,
+ ur->ur_pipe->up_num,
+ ept->ep_phys,
+ (uint64_t) (uintptr_t) ptr,
+ len);
+// ohci_dumped(ed);
+ }
+
+ curtd = OHCI_PTOV(BSWAP32(ed->ed_tailp));
+ curtransfer = ohci_transfer_from_td(softc,curtd);
+
+ if (len == 0) {
+ newtailtransfer = _ohci_allocxfer(softc);
+ newtailtd = ohci_td_from_transfer(softc,newtailtransfer);
+ curtd->td_cbp = 0;
+ curtd->td_be = 0;
+ curtd->td_next_td = BSWAP32(OHCI_VTOP(newtailtd));
+ curtd->td_control = BSWAP32(tdcontrol);
+ curtransfer->t_next = newtailtransfer;
+ curtransfer->t_ref = ur;
+ curtransfer->t_length = 0;
+ if (ohcidebug > 1) { printf("QueueTD: "); ohci_dumptd(curtd); }
+ ur->ur_tdcount++;
+ }
+ else {
+ /* Noncoherent DMA: need to flush user buffer to real memory first */
+ OHCI_FLUSH_RANGE(ptr,len);
+ while (len > 0) {
+ amtcopy = len;
+ if (amtcopy > pktlen) amtcopy = pktlen;
+ newtailtransfer = _ohci_allocxfer(softc);
+ newtailtd = ohci_td_from_transfer(softc,newtailtransfer);
+ curtd->td_cbp = BSWAP32(OHCI_VTOP(ptr));
+ curtd->td_be = BSWAP32(OHCI_VTOP(ptr+amtcopy)-1);
+ curtd->td_next_td = BSWAP32(OHCI_VTOP(newtailtd));
+ curtd->td_control = BSWAP32(tdcontrol);
+ curtransfer->t_next = newtailtransfer;
+ curtransfer->t_ref = ur;
+ curtransfer->t_length = amtcopy;
+ if (ohcidebug > 1) { printf("QueueTD: "); ohci_dumptd(curtd); }
+ curtd = newtailtd;
+ curtransfer = ohci_transfer_from_td(softc,curtd);
+ ptr += amtcopy;
+ len -= amtcopy;
+ ur->ur_tdcount++;
+ }
+ }
+
+ curtd = OHCI_PTOV(BSWAP32(ed->ed_headp & M_OHCI_ED_PTRMASK));
+ ed->ed_tailp = BSWAP32(OHCI_VTOP(newtailtd));
+
+ /*
+ * Prod the controller depending on what type of list we put
+ * a TD on.
+ */
+
+ if (ept->ep_flags & UP_TYPE_BULK) {
+ OHCI_WRITECSR(softc,R_OHCI_CMDSTATUS,M_OHCI_CMDSTATUS_BLF);
+ }
+ else {
+ /* XXX should probably make sure we're UP_TYPE_CONTROL here */
+ OHCI_WRITECSR(softc,R_OHCI_CMDSTATUS,M_OHCI_CMDSTATUS_CLF);
+ }
+
+ return 0;
+}
+
+/* *********************************************************************
+ * Driver structure
+ ********************************************************************* */
+
+usb_hcdrv_t ohci_driver = {
+ ohci_create,
+ ohci_delete,
+ ohci_start,
+ ohci_stop,
+ ohci_intr,
+ ohci_ept_create,
+ ohci_ept_delete,
+ ohci_ept_setmps,
+ ohci_ept_setaddr,
+ ohci_ept_cleartoggle,
+ ohci_xfer
+};
+
+/* *********************************************************************
+ * Root Hub
+ *
+ * Data structures and functions
+ ********************************************************************* */
+
+/*
+ * Data structures and routines to emulate the root hub.
+ */
+static usb_device_descr_t ohci_root_devdsc = {
+ sizeof(usb_device_descr_t), /* bLength */
+ USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
+ USBWORD(0x0100), /* bcdUSB */
+ USB_DEVICE_CLASS_HUB, /* bDeviceClass */
+ 0, /* bDeviceSubClass */
+ 0, /* bDeviceProtocol */
+ 64, /* bMaxPacketSize0 */
+ USBWORD(0), /* idVendor */
+ USBWORD(0), /* idProduct */
+ USBWORD(0x0100), /* bcdDevice */
+ 1, /* iManufacturer */
+ 2, /* iProduct */
+ 0, /* iSerialNumber */
+ 1 /* bNumConfigurations */
+};
+
+static usb_config_descr_t ohci_root_cfgdsc = {
+ sizeof(usb_config_descr_t), /* bLength */
+ USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
+ USBWORD(
+ sizeof(usb_config_descr_t) +
+ sizeof(usb_interface_descr_t) +
+ sizeof(usb_endpoint_descr_t)), /* wTotalLength */
+ 1, /* bNumInterfaces */
+ 1, /* bConfigurationValue */
+ 0, /* iConfiguration */
+ USB_CONFIG_SELF_POWERED, /* bmAttributes */
+ 0 /* MaxPower */
+};
+
+static usb_interface_descr_t ohci_root_ifdsc = {
+ sizeof(usb_interface_descr_t), /* bLength */
+ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
+ 0, /* bInterfaceNumber */
+ 0, /* bAlternateSetting */
+ 1, /* bNumEndpoints */
+ USB_INTERFACE_CLASS_HUB, /* bInterfaceClass */
+ 0, /* bInterfaceSubClass */
+ 0, /* bInterfaceProtocol */
+ 0 /* iInterface */
+};
+
+static usb_endpoint_descr_t ohci_root_epdsc = {
+ sizeof(usb_endpoint_descr_t), /* bLength */
+ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
+ (USB_ENDPOINT_DIRECTION_IN | 1), /* bEndpointAddress */
+ USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */
+ USBWORD(8), /* wMaxPacketSize */
+ 255 /* bInterval */
+};
+
+static usb_hub_descr_t ohci_root_hubdsc = {
+ USB_HUB_DESCR_SIZE, /* bLength */
+ USB_HUB_DESCRIPTOR_TYPE, /* bDescriptorType */
+ 0, /* bNumberOfPorts */
+ USBWORD(0), /* wHubCharacteristics */
+ 0, /* bPowreOnToPowerGood */
+ 0, /* bHubControl Current */
+ {0} /* bRemoveAndPowerMask */
+};
+
+/* *********************************************************************
+ * ohci_roothb_strdscr(ptr,str)
+ *
+ * Construct a string descriptor for root hub requests
+ *
+ * Input parameters:
+ * ptr - pointer to where to put descriptor
+ * str - regular string to put into descriptor
+ *
+ * Return value:
+ * number of bytes written to descriptor
+ ********************************************************************* */
+
+static int ohci_roothub_strdscr(uint8_t *ptr,char *str)
+{
+ uint8_t *p = ptr;
+
+ *p++ = strlen(str)*2 + 2; /* Unicode strings */
+ *p++ = USB_STRING_DESCRIPTOR_TYPE;
+ while (*str) {
+ *p++ = *str++;
+ *p++ = 0;
+ }
+ return (p - ptr);
+}
+
+/* *********************************************************************
+ * ohci_roothub_req(softc,req)
+ *
+ * Handle a descriptor request on the control pipe for the
+ * root hub. We pretend to be a real root hub here and
+ * return all the standard descriptors.
+ *
+ * Input parameters:
+ * softc - our OHCI controller
+ * req - a usb request (completed immediately)
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int ohci_roothub_req(ohci_softc_t *softc,usb_device_request_t *req)
+{
+ uint8_t *ptr;
+ uint16_t wLength;
+ uint16_t wValue;
+ uint16_t wIndex;
+ usb_port_status_t ups;
+ usb_hub_descr_t hdsc;
+ uint32_t status;
+ uint32_t statport;
+ uint32_t tmpval;
+ int res = 0;
+
+ ptr = softc->ohci_rh_buf;
+
+ wLength = GETUSBFIELD(req,wLength);
+ wValue = GETUSBFIELD(req,wValue);
+ wIndex = GETUSBFIELD(req,wIndex);
+
+ switch (REQSW(req->bRequest,req->bmRequestType)) {
+
+ case REQCODE(USB_REQUEST_GET_STATUS,USBREQ_DIR_IN,USBREQ_TYPE_STD,USBREQ_REC_DEVICE):
+ *ptr++ = (USB_GETSTATUS_SELF_POWERED & 0xFF);
+ *ptr++ = (USB_GETSTATUS_SELF_POWERED >> 8);
+ break;
+
+ case REQCODE(USB_REQUEST_GET_STATUS,USBREQ_DIR_IN,USBREQ_TYPE_STD,USBREQ_REC_ENDPOINT):
+ case REQCODE(USB_REQUEST_GET_STATUS,USBREQ_DIR_IN,USBREQ_TYPE_STD,USBREQ_REC_INTERFACE):
+ *ptr++ = 0;
+ *ptr++ = 0;
+ break;
+
+ case REQCODE(USB_REQUEST_GET_STATUS,USBREQ_DIR_IN,USBREQ_TYPE_CLASS,USBREQ_REC_OTHER):
+ status = OHCI_READCSR(softc,(R_OHCI_RHPORTSTATUS(wIndex)));
+ if (ohcidebug > 0) { printf("RHGetStatus: "); ohci_dumpportstat(wIndex,status);}
+ PUTUSBFIELD((&ups),wPortStatus,(status & 0xFFFF));
+ PUTUSBFIELD((&ups),wPortChange,(status >> 16));
+ memcpy(ptr,&ups,sizeof(ups));
+ ptr += sizeof(ups);
+ break;
+
+ case REQCODE(USB_REQUEST_GET_STATUS,USBREQ_DIR_IN,USBREQ_TYPE_CLASS,USBREQ_REC_DEVICE):
+ *ptr++ = 0;
+ *ptr++ = 0;
+ *ptr++ = 0;
+ *ptr++ = 0;
+ break;
+
+ case REQCODE(USB_REQUEST_CLEAR_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_DEVICE):
+ case REQCODE(USB_REQUEST_CLEAR_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_INTERFACE):
+ case REQCODE(USB_REQUEST_CLEAR_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_ENDPOINT):
+ /* do nothing, not supported */
+ break;
+
+ case REQCODE(USB_REQUEST_CLEAR_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_CLASS,USBREQ_REC_OTHER):
+ statport = R_OHCI_RHPORTSTATUS(wIndex);
+ if (ohcidebug> 0) {
+ printf("RHClearFeature(%d): ",wValue); ohci_dumpportstat(wIndex,OHCI_READCSR(softc,statport));
+ }
+ switch (wValue) {
+ case USB_PORT_FEATURE_CONNECTION:
+ break;
+ case USB_PORT_FEATURE_ENABLE:
+ OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_CCS);
+ break;
+ case USB_PORT_FEATURE_SUSPEND:
+ OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_POCI);
+ break;
+ case USB_PORT_FEATURE_OVER_CURRENT:
+ break;
+ case USB_PORT_FEATURE_RESET:
+ break;
+ case USB_PORT_FEATURE_POWER:
+ OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_LSDA);
+ break;
+ case USB_PORT_FEATURE_LOW_SPEED:
+ break;
+ case USB_PORT_FEATURE_C_PORT_CONNECTION:
+ OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_CSC);
+ break;
+ case USB_PORT_FEATURE_C_PORT_ENABLE:
+ OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PESC);
+ break;
+ case USB_PORT_FEATURE_C_PORT_SUSPEND:
+ OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PSSC);
+ break;
+ case USB_PORT_FEATURE_C_PORT_OVER_CURRENT:
+ OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_OCIC);
+ break;
+ case USB_PORT_FEATURE_C_PORT_RESET:
+ OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PRSC);
+ break;
+
+ }
+
+ /*
+ * If we've cleared all of the conditions that
+ * want our attention on the port status,
+ * then we can accept port status interrupts again.
+ */
+
+ if ((wValue >= USB_PORT_FEATURE_C_PORT_CONNECTION) &&
+ (wValue <= USB_PORT_FEATURE_C_PORT_RESET)) {
+ status = OHCI_READCSR(softc,statport);
+ if ((status & M_OHCI_RHPORTSTAT_ALLC) == 0) {
+ softc->ohci_intdisable &= ~M_OHCI_INT_RHSC;
+ }
+ }
+ break;
+
+ case REQCODE(USB_REQUEST_SET_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_DEVICE):
+ case REQCODE(USB_REQUEST_SET_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_INTERFACE):
+ case REQCODE(USB_REQUEST_SET_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_ENDPOINT):
+ res = -1;
+ break;
+
+ case REQCODE(USB_REQUEST_SET_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_CLASS,USBREQ_REC_DEVICE):
+ /* nothing */
+ break;
+
+ case REQCODE(USB_REQUEST_SET_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_CLASS,USBREQ_REC_OTHER):
+ statport = R_OHCI_RHPORTSTATUS(wIndex);
+ switch (wValue) {
+ case USB_PORT_FEATURE_CONNECTION:
+ break;
+ case USB_PORT_FEATURE_ENABLE:
+ OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PES);
+ break;
+ case USB_PORT_FEATURE_SUSPEND:
+ OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PSS);
+ break;
+ case USB_PORT_FEATURE_OVER_CURRENT:
+ break;
+ case USB_PORT_FEATURE_RESET:
+ OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PRS);
+ for (;;) { /* XXX timer */
+ usb_delay_ms(softc->ohci_bus,100);
+ if (!(OHCI_READCSR(softc,statport) & M_OHCI_RHPORTSTAT_PRS)) break;
+ }
+ break;
+ case USB_PORT_FEATURE_POWER:
+ OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PPS);
+ break;
+ case USB_PORT_FEATURE_LOW_SPEED:
+ break;
+ case USB_PORT_FEATURE_C_PORT_CONNECTION:
+ break;
+ case USB_PORT_FEATURE_C_PORT_ENABLE:
+ break;
+ case USB_PORT_FEATURE_C_PORT_SUSPEND:
+ break;
+ case USB_PORT_FEATURE_C_PORT_OVER_CURRENT:
+ break;
+ case USB_PORT_FEATURE_C_PORT_RESET:
+ break;
+
+ }
+
+ break;
+
+ case REQCODE(USB_REQUEST_SET_ADDRESS,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_DEVICE):
+ softc->ohci_rh_newaddr = wValue;
+ break;
+
+ case REQCODE(USB_REQUEST_GET_DESCRIPTOR,USBREQ_DIR_IN,USBREQ_TYPE_STD,USBREQ_REC_DEVICE):
+ switch (wValue >> 8) {
+ case USB_DEVICE_DESCRIPTOR_TYPE:
+ memcpy(ptr,&ohci_root_devdsc,sizeof(ohci_root_devdsc));
+ ptr += sizeof(ohci_root_devdsc);
+ break;
+ case USB_CONFIGURATION_DESCRIPTOR_TYPE:
+ memcpy(ptr,&ohci_root_cfgdsc,sizeof(ohci_root_cfgdsc));
+ ptr += sizeof(ohci_root_cfgdsc);
+ memcpy(ptr,&ohci_root_ifdsc,sizeof(ohci_root_ifdsc));
+ ptr += sizeof(ohci_root_ifdsc);
+ memcpy(ptr,&ohci_root_epdsc,sizeof(ohci_root_epdsc));
+ ptr += sizeof(ohci_root_epdsc);
+ break;
+ case USB_STRING_DESCRIPTOR_TYPE:
+ switch (wValue & 0xFF) {
+ case 1:
+ ptr += ohci_roothub_strdscr(ptr,"Generic");
+ break;
+ case 2:
+ ptr += ohci_roothub_strdscr(ptr,"Root Hub");
+ break;
+ default:
+ *ptr++ = 0;
+ break;
+ }
+ break;
+ default:
+ res = -1;
+ break;
+ }
+ break;
+
+ case REQCODE(USB_REQUEST_GET_DESCRIPTOR,USBREQ_DIR_IN,USBREQ_TYPE_CLASS,USBREQ_REC_DEVICE):
+ memcpy(&hdsc,&ohci_root_hubdsc,sizeof(hdsc));
+ hdsc.bNumberOfPorts = softc->ohci_ndp;
+ status = OHCI_READCSR(softc,R_OHCI_RHDSCRA);
+ tmpval = 0;
+ if (status & M_OHCI_RHDSCRA_NPS) tmpval |= USB_HUBCHAR_PWR_NONE;
+ if (status & M_OHCI_RHDSCRA_PSM) tmpval |= USB_HUBCHAR_PWR_GANGED;
+ else tmpval |= USB_HUBCHAR_PWR_IND;
+ PUTUSBFIELD((&hdsc),wHubCharacteristics,tmpval);
+ tmpval = G_OHCI_RHDSCRA_POTPGT(status);
+ hdsc.bPowerOnToPowerGood = tmpval;
+ hdsc.bDescriptorLength = USB_HUB_DESCR_SIZE + 1;
+ status = OHCI_READCSR(softc,R_OHCI_RHDSCRB);
+ hdsc.bRemoveAndPowerMask[0] = (uint8_t) status;
+ memcpy(ptr,&hdsc,sizeof(hdsc));
+ ptr += sizeof(hdsc);
+ break;
+
+ case REQCODE(USB_REQUEST_SET_DESCRIPTOR,USBREQ_DIR_OUT,USBREQ_TYPE_CLASS,USBREQ_REC_DEVICE):
+ /* nothing */
+ break;
+
+ case REQCODE(USB_REQUEST_GET_CONFIGURATION,USBREQ_DIR_IN,USBREQ_TYPE_STD,USBREQ_REC_DEVICE):
+ *ptr++ = softc->ohci_rh_conf;
+ break;
+
+ case REQCODE(USB_REQUEST_SET_CONFIGURATION,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_DEVICE):
+ softc->ohci_rh_conf = wValue;
+ break;
+
+ case REQCODE(USB_REQUEST_GET_INTERFACE,USBREQ_DIR_IN,USBREQ_TYPE_STD,USBREQ_REC_INTERFACE):
+ *ptr++ = 0;
+ break;
+
+ case REQCODE(USB_REQUEST_SET_INTERFACE,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_INTERFACE):
+ /* nothing */
+ break;
+
+ case REQCODE(USB_REQUEST_SYNC_FRAME,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_ENDPOINT):
+ /* nothing */
+ break;
+ }
+
+ softc->ohci_rh_ptr = softc->ohci_rh_buf;
+ softc->ohci_rh_len = ptr - softc->ohci_rh_buf;
+
+ return res;
+}
+
+/* *********************************************************************
+ * ohci_roothub_statchg(softc)
+ *
+ * This routine is called from the interrupt service routine
+ * (well, polling routine) for the ohci controller. If the
+ * controller notices a root hub status change, it dequeues an
+ * interrupt transfer from the root hub's queue and completes
+ * it here.
+ *
+ * Input parameters:
+ * softc - our OHCI controller
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void ohci_roothub_statchg(ohci_softc_t *softc)
+{
+ usbreq_t *ur;
+ uint32_t status;
+ uint8_t portstat = 0;
+ int idx;
+
+ /* Note: this only works up to 8 ports */
+ for (idx = 1; idx <= softc->ohci_ndp; idx++) {
+ status = OHCI_READCSR(softc,R_OHCI_RHPORTSTATUS(idx));
+ if (status & M_OHCI_RHPORTSTAT_ALLC) {
+ portstat = (1<<idx);
+ }
+ }
+
+ if (portstat != 0) {
+ softc->ohci_intdisable |= M_OHCI_INT_RHSC;
+ }
+
+ ur = (usbreq_t *) q_deqnext(&(softc->ohci_rh_intrq));
+ if (!ur) return; /* no requests pending, ignore it */
+
+ memset(ur->ur_buffer,0,ur->ur_length);
+ ur->ur_buffer[0] = portstat;
+ ur->ur_xferred = ur->ur_length;
+
+ usb_complete_request(ur,0);
+}
+
+/* *********************************************************************
+ * ohci_roothub_xfer(softc,req)
+ *
+ * Handle a root hub xfer - ohci_xfer transfers control here
+ * if we detect the address of the root hub - no actual transfers
+ * go out on the wire, we just handle the requests directly to
+ * make it look like a hub is attached.
+ *
+ * This seems to be common practice in the USB world, so we do
+ * it here too.
+ *
+ * Input parameters:
+ * softc - our OHCI controller structure
+ * req - usb request destined for host controller
+ *
+ * Return value:
+ * 0 if ok
+ * else error
+ ********************************************************************* */
+
+static int ohci_roothub_xfer(usbbus_t *bus,usb_ept_t *uept,usbreq_t *ur)
+{
+ ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc;
+ ohci_endpoint_t *ept = (ohci_endpoint_t *) uept;
+ int res;
+
+ switch (ept->ep_num) {
+
+ /*
+ * CONTROL ENDPOINT
+ */
+ case 0:
+
+ /*
+ * Three types of transfers: OUT (SETUP), IN (data), or STATUS.
+ * figure out which is which.
+ */
+
+ if (ur->ur_flags & UR_FLAG_SETUP) {
+ /*
+ * SETUP packet - this is an OUT request to the control
+ * pipe. We emulate the hub request here.
+ */
+ usb_device_request_t *req;
+
+ req = (usb_device_request_t *) ur->ur_buffer;
+
+ res = ohci_roothub_req(softc,req);
+ if (res != 0) printf("Root hub request returned an error\n");
+
+ ur->ur_xferred = ur->ur_length;
+ ur->ur_status = 0;
+ usb_complete_request(ur,0);
+ }
+
+ else if (ur->ur_flags & UR_FLAG_STATUS_IN) {
+ /*
+ * STATUS IN : it's sort of like a dummy IN request
+ * to acknowledge a SETUP packet that otherwise has no
+ * status. Just complete the usbreq.
+ */
+
+ if (softc->ohci_rh_newaddr != -1) {
+ softc->ohci_rh_addr = softc->ohci_rh_newaddr;
+ softc->ohci_rh_newaddr = -1;
+ }
+
+ ur->ur_status = 0;
+ ur->ur_xferred = 0;
+ usb_complete_request(ur,0);
+ }
+
+ else if (ur->ur_flags & UR_FLAG_STATUS_OUT) {
+ /*
+ * STATUS OUT : it's sort of like a dummy OUT request
+ */
+ ur->ur_status = 0;
+ ur->ur_xferred = 0;
+ usb_complete_request(ur,0);
+ }
+
+ else if (ur->ur_flags & UR_FLAG_IN) {
+ /*
+ * IN : return data from the root hub
+ */
+ int amtcopy;
+
+ amtcopy = softc->ohci_rh_len;
+ if (amtcopy > ur->ur_length) amtcopy = ur->ur_length;
+
+ memcpy(ur->ur_buffer,softc->ohci_rh_ptr,amtcopy);
+
+ softc->ohci_rh_ptr += amtcopy;
+ softc->ohci_rh_len -= amtcopy;
+
+ ur->ur_status = 0;
+ ur->ur_xferred = amtcopy;
+ usb_complete_request(ur,0);
+ }
+
+ else {
+ printf("Unknown root hub transfer type\n");
+ return -1;
+ }
+ break;
+
+ /*
+ * INTERRUPT ENDPOINT
+ */
+
+ case 1: /* interrupt pipe */
+ if (ur->ur_flags & UR_FLAG_IN) {
+ q_enqueue(&(softc->ohci_rh_intrq),(queue_t *) ur);
+ }
+ break;
+
+ }
+
+
+ return 0;
+}
diff --git a/cfe/cfe/usb/ohci.h b/cfe/cfe/usb/ohci.h
new file mode 100644
index 0000000..06368e5
--- /dev/null
+++ b/cfe/cfe/usb/ohci.h
@@ -0,0 +1,490 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * OHCI defs File: ohci.h
+ *
+ * Open Host controller interface definitions
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+/* *********************************************************************
+ * Macros to muck with bitfields
+ ********************************************************************* */
+
+#define _OHCI_MAKE32(x) ((uint32_t)(x))
+
+/*
+ * Make a mask for 1 bit at position 'n'
+ */
+
+#define _OHCI_MAKEMASK1(n) (_OHCI_MAKE32(1) << _OHCI_MAKE32(n))
+
+/*
+ * Make a mask for 'v' bits at position 'n'
+ */
+
+#define _OHCI_MAKEMASK(v,n) (_OHCI_MAKE32((_OHCI_MAKE32(1)<<(v))-1) << _OHCI_MAKE32(n))
+
+/*
+ * Make a value at 'v' at bit position 'n'
+ */
+
+#define _OHCI_MAKEVALUE(v,n) (_OHCI_MAKE32(v) << _OHCI_MAKE32(n))
+#define _OHCI_GETVALUE(v,n,m) ((_OHCI_MAKE32(v) & _OHCI_MAKE32(m)) >> _OHCI_MAKE32(n))
+
+
+
+/* *********************************************************************
+ * Endpoint Descriptor (interrupt, bulk)
+ ********************************************************************* */
+
+#define OHCI_ED_ALIGN 32
+
+typedef struct ohci_ed_s {
+ uint32_t ed_control;
+ uint32_t ed_tailp;
+ uint32_t ed_headp;
+ uint32_t ed_next_ed;
+} ohci_ed_t;
+
+#define S_OHCI_ED_FA 0
+#define M_OHCI_ED_FA _OHCI_MAKEMASK(7,S_OHCI_ED_FA)
+#define V_OHCI_ED_FA(x) _OHCI_MAKEVALUE(x,S_OHCI_ED_FA)
+#define G_OHCI_ED_FA(x) _OHCI_GETVALUE(x,S_OHCI_ED_FA,M_OHCI_ED_FA)
+
+#define S_OHCI_ED_EN 7
+#define M_OHCI_ED_EN _OHCI_MAKEMASK(4,S_OHCI_ED_EN)
+#define V_OHCI_ED_EN(x) _OHCI_MAKEVALUE(x,S_OHCI_ED_EN)
+#define G_OHCI_ED_EN(x) _OHCI_GETVALUE(x,S_OHCI_ED_EN,M_OHCI_ED_EN)
+
+#define S_OHCI_ED_DIR 11
+#define M_OHCI_ED_DIR _OHCI_MAKEMASK(2,S_OHCI_ED_DIR)
+#define V_OHCI_ED_DIR(x) _OHCI_MAKEVALUE(x,S_OHCI_ED_DIR)
+#define G_OHCI_ED_DIR(x) _OHCI_GETVALUE(x,S_OHCI_ED_DIR,M_OHCI_ED_DIR)
+
+#define K_OHCI_ED_DIR_FROMTD 0
+#define K_OHCI_ED_DIR_OUT 1
+#define K_OHCI_ED_DIR_IN 2
+
+#define M_OHCI_ED_LOWSPEED _OHCI_MAKEMASK1(13)
+#define M_OHCI_ED_SKIP _OHCI_MAKEMASK1(14)
+#define M_OHCI_ED_ISOCFMT _OHCI_MAKEMASK1(15)
+
+#define S_OHCI_ED_MPS 16
+#define M_OHCI_ED_MPS _OHCI_MAKEMASK(11,S_OHCI_ED_MPS)
+#define V_OHCI_ED_MPS(x) _OHCI_MAKEVALUE(x,S_OHCI_ED_MPS)
+#define G_OHCI_ED_MPS(x) _OHCI_GETVALUE(x,S_OHCI_ED_MPS,M_OHCI_ED_MPS)
+
+#define M_OHCI_ED_PTRMASK 0xFFFFFFF0
+#define M_OHCI_ED_HALT _OHCI_MAKEMASK1(0)
+#define M_OHCI_ED_TOGGLECARRY _OHCI_MAKEMASK1(1)
+
+/* *********************************************************************
+ * Transfer Descriptor
+ ********************************************************************* */
+
+#define OHCI_TD_ALIGN 32
+
+typedef struct ohci_td_s {
+ uint32_t td_control;
+ uint32_t td_cbp;
+ uint32_t td_next_td;
+ uint32_t td_be;
+} ohci_td_t;
+
+#define M_OHCI_TD_SHORTOK _OHCI_MAKEMASK1(18)
+
+#define S_OHCI_TD_PID 19
+#define M_OHCI_TD_PID _OHCI_MAKEMASK(2,S_OHCI_TD_PID)
+#define V_OHCI_TD_PID(x) _OHCI_MAKEVALUE(x,S_OHCI_TD_PID)
+#define G_OHCI_TD_PID(x) _OHCI_GETVALUE(x,S_OHCI_TD_PID,M_OHCI_TD_PID)
+
+#define K_OHCI_TD_SETUP 0
+#define K_OHCI_TD_OUT 1
+#define K_OHCI_TD_IN 2
+#define K_OHCI_TD_RESERVED 3
+
+#define V_OHCI_TD_SETUP V_OHCI_TD_PID(K_OHCI_TD_SETUP)
+#define V_OHCI_TD_OUT V_OHCI_TD_PID(K_OHCI_TD_OUT)
+#define V_OHCI_TD_IN V_OHCI_TD_PID(K_OHCI_TD_IN)
+#define V_OHCI_TD_RESERVED V_OHCI_TD_PID(K_OHCI_TD_RESERVED)
+
+#define S_OHCI_TD_DI 21
+#define M_OHCI_TD_DI _OHCI_MAKEMASK(3,S_OHCI_TD_DI)
+#define V_OHCI_TD_DI(x) _OHCI_MAKEVALUE(x,S_OHCI_TD_DI)
+#define G_OHCI_TD_DI(x) _OHCI_GETVALUE(x,S_OHCI_TD_DI,M_OHCI_TD_DI)
+
+#define K_OHCI_TD_NOINTR 7
+#define V_OHCI_TD_NOINTR V_OHCI_TD_DI(K_OHCI_TD_NOINTR)
+
+#define S_OHCI_TD_DT 24
+#define M_OHCI_TD_DT _OHCI_MAKEMASK(2,S_OHCI_TD_DT)
+#define V_OHCI_TD_DT(x) _OHCI_MAKEVALUE(x,S_OHCI_TD_DT)
+#define G_OHCI_TD_DT(x) _OHCI_GETVALUE(x,S_OHCI_TD_DT,M_OHCI_TD_DT)
+
+#define K_OHCI_TD_DT_DATA0 2
+#define K_OHCI_TD_DT_DATA1 3
+#define K_OHCI_TD_DT_TCARRY 0
+
+#define S_OHCI_TD_EC 26
+#define M_OHCI_TD_EC _OHCI_MAKEMASK(2,S_OHCI_TD_EC)
+#define V_OHCI_TD_EC(x) _OHCI_MAKEVALUE(x,S_OHCI_TD_EC)
+#define G_OHCI_TD_EC(x) _OHCI_GETVALUE(x,S_OHCI_TD_EC,M_OHCI_TD_EC)
+
+#define S_OHCI_TD_CC 28
+#define M_OHCI_TD_CC _OHCI_MAKEMASK(4,S_OHCI_TD_CC)
+#define V_OHCI_TD_CC(x) _OHCI_MAKEVALUE(x,S_OHCI_TD_CC)
+#define G_OHCI_TD_CC(x) _OHCI_GETVALUE(x,S_OHCI_TD_CC,M_OHCI_TD_CC)
+
+#define K_OHCI_CC_NOERROR 0
+#define K_OHCI_CC_CRC 1
+#define K_OHCI_CC_BITSTUFFING 2
+#define K_OHCI_CC_DATATOGGLEMISMATCH 3
+#define K_OHCI_CC_STALL 4
+#define K_OHCI_CC_DEVICENOTRESPONDING 5
+#define K_OHCI_CC_PIDCHECKFAILURE 6
+#define K_OHCI_CC_UNEXPECTEDPID 7
+#define K_OHCI_CC_DATAOVERRUN 8
+#define K_OHCI_CC_DATAUNDERRUN 9
+#define K_OHCI_CC_BUFFEROVERRUN 12
+#define K_OHCI_CC_BUFFERUNDERRUN 13
+#define K_OHCI_CC_NOTACCESSED 15
+
+#define K_OHCI_CC_CANCELLED 0xFF
+
+#define OHCI_TD_MAX_DATA 8192
+
+
+/* *********************************************************************
+ * Endpoint descriptor (isochronous)
+ ********************************************************************* */
+
+/*
+ * TBA
+ */
+
+/* *********************************************************************
+ * Host Controller Communications Area (HCCA)
+ ********************************************************************* */
+
+#define OHCI_INTTABLE_SIZE 32
+
+#define OHCI_HCCA_ALIGN 256 /* Align on 256-byte boundary */
+
+typedef struct ohci_hcca_s {
+ uint32_t hcca_inttable[OHCI_INTTABLE_SIZE];
+ uint32_t hcca_framenum; /* note: actually two 16-bit fields */
+ uint32_t hcca_donehead;
+ uint32_t hcca_reserved[29]; /* round to 256 bytes */
+ uint32_t hcca_pad;
+} ohci_hcca_t;
+
+/* *********************************************************************
+ * Registers
+ ********************************************************************* */
+
+#define _OHCI_REGIDX(x) ((x)*4)
+
+#define R_OHCI_REVISION _OHCI_REGIDX(0)
+#define R_OHCI_CONTROL _OHCI_REGIDX(1)
+#define R_OHCI_CMDSTATUS _OHCI_REGIDX(2)
+#define R_OHCI_INTSTATUS _OHCI_REGIDX(3)
+#define R_OHCI_INTENABLE _OHCI_REGIDX(4)
+#define R_OHCI_INTDISABLE _OHCI_REGIDX(5)
+#define R_OHCI_HCCA _OHCI_REGIDX(6)
+#define R_OHCI_PERIODCURRENTED _OHCI_REGIDX(7)
+#define R_OHCI_CONTROLHEADED _OHCI_REGIDX(8)
+#define R_OHCI_CONTROLCURRENTED _OHCI_REGIDX(9)
+#define R_OHCI_BULKHEADED _OHCI_REGIDX(10)
+#define R_OHCI_BULKCURRENTED _OHCI_REGIDX(11)
+#define R_OHCI_DONEHEAD _OHCI_REGIDX(12)
+#define R_OHCI_FMINTERVAL _OHCI_REGIDX(13)
+#define R_OHCI_FMREMAINING _OHCI_REGIDX(14)
+#define R_OHCI_FMNUMBER _OHCI_REGIDX(15)
+#define R_OHCI_PERIODICSTART _OHCI_REGIDX(16)
+#define R_OHCI_LSTHRESHOLD _OHCI_REGIDX(17)
+#define R_OHCI_RHDSCRA _OHCI_REGIDX(18)
+#define R_OHCI_RHDSCRB _OHCI_REGIDX(19)
+#define R_OHCI_RHSTATUS _OHCI_REGIDX(20)
+#define R_OHCI_RHPORTSTATUS(x) _OHCI_REGIDX(20+(x)) /* note: 1-based! */
+
+
+/*
+ * R_OHCI_REVISION
+ */
+
+#define S_OHCI_REV_REV 0
+#define M_OHCI_REV_REV _OHCI_MAKEMASK(8,S_OHCI_REV_REV)
+#define V_OHCI_REV_REV(x) _OHCI_MAKEVALUE(x,S_OHCI_REV_REV)
+#define G_OHCI_REV_REV(x) _OHCI_GETVALUE(x,S_OHCI_REV_REV,M_OHCI_REV_REV)
+#define K_OHCI_REV_11 0x10
+
+/*
+ * R_OHCI_CONTROL
+ */
+
+#define S_OHCI_CONTROL_CBSR 0
+#define M_OHCI_CONTROL_CBSR _OHCI_MAKEMASK(2,S_OHCI_CONTROL_CBSR)
+#define V_OHCI_CONTROL_CBSR(x) _OHCI_MAKEVALUE(x,S_OHCI_CONTROL_CBSR)
+#define G_OHCI_CONTROL_CBSR(x) _OHCI_GETVALUE(x,S_OHCI_CONTROL_CBSR,M_OHCI_CONTROL_CBSR)
+
+#define K_OHCI_CBSR_11 0
+#define K_OHCI_CBSR_21 1
+#define K_OHCI_CBSR_31 2
+#define K_OHCI_CBSR_41 3
+
+#define M_OHCI_CONTROL_PLE _OHCI_MAKEMASK1(2)
+#define M_OHCI_CONTROL_IE _OHCI_MAKEMASK1(3)
+#define M_OHCI_CONTROL_CLE _OHCI_MAKEMASK1(4)
+#define M_OHCI_CONTROL_BLE _OHCI_MAKEMASK1(5)
+
+#define S_OHCI_CONTROL_HCFS 6
+#define M_OHCI_CONTROL_HCFS _OHCI_MAKEMASK(2,S_OHCI_CONTROL_HCFS)
+#define V_OHCI_CONTROL_HCFS(x) _OHCI_MAKEVALUE(x,S_OHCI_CONTROL_HCFS)
+#define G_OHCI_CONTROL_HCFS(x) _OHCI_GETVALUE(x,S_OHCI_CONTROL_HCFS,M_OHCI_CONTROL_HCFS)
+
+#define K_OHCI_HCFS_RESET 0
+#define K_OHCI_HCFS_RESUME 1
+#define K_OHCI_HCFS_OPERATIONAL 2
+#define K_OHCI_HCFS_SUSPEND 3
+
+#define M_OHCI_CONTROL_IR _OHCI_MAKEMASK1(8)
+#define M_OHCI_CONTROL_RWC _OHCI_MAKEMASK1(9)
+#define M_OHCI_CONTROL_RWE _OHCI_MAKEMASK1(10)
+
+/*
+ * R_OHCI_CMDSTATUS
+ */
+
+#define M_OHCI_CMDSTATUS_HCR _OHCI_MAKEMASK1(0)
+#define M_OHCI_CMDSTATUS_CLF _OHCI_MAKEMASK1(1)
+#define M_OHCI_CMDSTATUS_BLF _OHCI_MAKEMASK1(2)
+#define M_OHCI_CMDSTATUS_OCR _OHCI_MAKEMASK1(3)
+
+#define S_OHCI_CMDSTATUS_SOC 16
+#define M_OHCI_CMDSTATUS_SOC _OHCI_MAKEMASK(2,S_OHCI_CMDSTATUS_SOC)
+#define V_OHCI_CMDSTATUS_SOC(x) _OHCI_MAKEVALUE(x,S_OHCI_CMDSTATUS_SOC)
+#define G_OHCI_CMDSTATUS_SOC(x) _OHCI_GETVALUE(x,S_OHCI_CMDSTATUS_SOC,M_OHCI_CMDSTATUS_SOC)
+
+/*
+ * R_OHCI_INTSTATUS, R_OHCI_INTENABLE, R_OHCI_INTDISABLE
+ */
+
+
+#define M_OHCI_INT_SO _OHCI_MAKEMASK1(0)
+#define M_OHCI_INT_WDH _OHCI_MAKEMASK1(1)
+#define M_OHCI_INT_SF _OHCI_MAKEMASK1(2)
+#define M_OHCI_INT_RD _OHCI_MAKEMASK1(3)
+#define M_OHCI_INT_UE _OHCI_MAKEMASK1(4)
+#define M_OHCI_INT_FNO _OHCI_MAKEMASK1(5)
+#define M_OHCI_INT_RHSC _OHCI_MAKEMASK1(6)
+#define M_OHCI_INT_OC _OHCI_MAKEMASK1(30)
+#define M_OHCI_INT_MIE _OHCI_MAKEMASK1(31)
+
+#define M_OHCI_INT_ALL M_OHCI_INT_SO | M_OHCI_INT_WDH | M_OHCI_INT_SF | \
+ M_OHCI_INT_RD | M_OHCI_INT_UE | M_OHCI_INT_FNO | \
+ M_OHCI_INT_RHSC | M_OHCI_INT_OC | M_OHCI_INT_MIE
+
+/*
+ * R_OHCI_FMINTERVAL
+ */
+
+
+#define S_OHCI_FMINTERVAL_FI 0
+#define M_OHCI_FMINTERVAL_FI _OHCI_MAKEMASK(14,S_OHCI_FMINTERVAL_FI)
+#define V_OHCI_FMINTERVAL_FI(x) _OHCI_MAKEVALUE(x,S_OHCI_FMINTERVAL_FI)
+#define G_OHCI_FMINTERVAL_FI(x) _OHCI_GETVALUE(x,S_OHCI_FMINTERVAL_FI,M_OHCI_FMINTERVAL_FI)
+
+#define S_OHCI_FMINTERVAL_FSMPS 16
+#define M_OHCI_FMINTERVAL_FSMPS _OHCI_MAKEMASK(15,S_OHCI_FMINTERVAL_FSMPS)
+#define V_OHCI_FMINTERVAL_FSMPS(x) _OHCI_MAKEVALUE(x,S_OHCI_FMINTERVAL_FSMPS)
+#define G_OHCI_FMINTERVAL_FSMPS(x) _OHCI_GETVALUE(x,S_OHCI_FMINTERVAL_FSMPS,M_OHCI_FMINTERVAL_FSMPS)
+
+#define OHCI_CALC_FSMPS(x) ((((x)-210)*6/7))
+
+
+#define M_OHCI_FMINTERVAL_FIT _OHCI_MAKEMASK1(31)
+
+/*
+ * R_OHCI_FMREMAINING
+ */
+
+
+#define S_OHCI_FMREMAINING_FR 0
+#define M_OHCI_FMREMAINING_FR _OHCI_MAKEMASK(14,S_OHCI_FMREMAINING_FR)
+#define V_OHCI_FMREMAINING_FR(x) _OHCI_MAKEVALUE(x,S_OHCI_FMREMAINING_FR)
+#define G_OHCI_FMREMAINING_FR(x) _OHCI_GETVALUE(x,S_OHCI_FMREMAINING_FR,M_OHCI_FMREMAINING_FR)
+
+#define M_OHCI_FMREMAINING_FRT _OHCI_MAKEMASK1(31)
+
+/*
+ * R_OHCI_RHDSCRA
+ */
+
+
+#define S_OHCI_RHDSCRA_NDP 0
+#define M_OHCI_RHDSCRA_NDP _OHCI_MAKEMASK(8,S_OHCI_RHDSCRA_NDP)
+#define V_OHCI_RHDSCRA_NDP(x) _OHCI_MAKEVALUE(x,S_OHCI_RHDSCRA_NDP)
+#define G_OHCI_RHDSCRA_NDP(x) _OHCI_GETVALUE(x,S_OHCI_RHDSCRA_NDP,M_OHCI_RHDSCRA_NDP)
+
+#define M_OHCI_RHDSCRA_PSM _OHCI_MAKEMASK1(8)
+#define M_OHCI_RHDSCRA_NPS _OHCI_MAKEMASK1(9)
+#define M_OHCI_RHDSCRA_DT _OHCI_MAKEMASK1(10)
+#define M_OHCI_RHDSCRA_OCPM _OHCI_MAKEMASK1(11)
+#define M_OHCI_RHDSCRA_NOCP _OHCI_MAKEMASK1(12)
+
+#define S_OHCI_RHDSCRA_POTPGT 24
+#define M_OHCI_RHDSCRA_POTPGT _OHCI_MAKEMASK(8,S_OHCI_RHDSCRA_POTPGT)
+#define V_OHCI_RHDSCRA_POTPGT(x) _OHCI_MAKEVALUE(x,S_OHCI_RHDSCRA_POTPGT)
+#define G_OHCI_RHDSCRA_POTPGT(x) _OHCI_GETVALUE(x,S_OHCI_RHDSCRA_POTPGT,M_OHCI_RHDSCRA_POTPGT)
+
+/*
+ * R_OHCI_RHDSCRB
+ */
+
+#define S_OHCI_RHDSCRB_DR 0
+#define M_OHCI_RHDSCRB_DR _OHCI_MAKEMASK(16,S_OHCI_RHDSCRB_DR)
+#define V_OHCI_RHDSCRB_DR(x) _OHCI_MAKEVALUE(x,S_OHCI_RHDSCRB_DR)
+#define G_OHCI_RHDSCRB_DR(x) _OHCI_GETVALUE(x,S_OHCI_RHDSCRB_DR,M_OHCI_RHDSCRB_DR)
+
+#define S_OHCI_RHDSCRB_PPCM 16
+#define M_OHCI_RHDSCRB_PPCM _OHCI_MAKEMASK(16,S_OHCI_RHDSCRB_PPCM)
+#define V_OHCI_RHDSCRB_PPCM(x) _OHCI_MAKEVALUE(x,S_OHCI_RHDSCRB_PPCM)
+#define G_OHCI_RHDSCRB_PPCM(x) _OHCI_GETVALUE(x,S_OHCI_RHDSCRB_PPCM,M_OHCI_RHDSCRB_PPCM)
+
+/*
+ * R_OHCI_RHSTATUS
+ */
+
+#define M_OHCI_RHSTATUS_LPS _OHCI_MAKEMASK1(0)
+#define M_OHCI_RHSTATUS_OCI _OHCI_MAKEMASK1(1)
+#define M_OHCI_RHSTATUS_DRWE _OHCI_MAKEMASK1(15)
+#define M_OHCI_RHSTATUS_LPSC _OHCI_MAKEMASK1(16)
+#define M_OHCI_RHSTATUS_OCIC _OHCI_MAKEMASK1(17)
+#define M_OHCI_RHSTATUS_CRWE _OHCI_MAKEMASK1(31)
+
+/*
+ * R_OHCI_RHPORTSTATUS
+ */
+
+#define M_OHCI_RHPORTSTAT_CCS _OHCI_MAKEMASK1(0)
+#define M_OHCI_RHPORTSTAT_PES _OHCI_MAKEMASK1(1)
+#define M_OHCI_RHPORTSTAT_PSS _OHCI_MAKEMASK1(2)
+#define M_OHCI_RHPORTSTAT_POCI _OHCI_MAKEMASK1(3)
+#define M_OHCI_RHPORTSTAT_PRS _OHCI_MAKEMASK1(4)
+#define M_OHCI_RHPORTSTAT_PPS _OHCI_MAKEMASK1(8)
+#define M_OHCI_RHPORTSTAT_LSDA _OHCI_MAKEMASK1(9)
+#define M_OHCI_RHPORTSTAT_CSC _OHCI_MAKEMASK1(16)
+#define M_OHCI_RHPORTSTAT_PESC _OHCI_MAKEMASK1(17)
+#define M_OHCI_RHPORTSTAT_PSSC _OHCI_MAKEMASK1(18)
+#define M_OHCI_RHPORTSTAT_OCIC _OHCI_MAKEMASK1(19)
+#define M_OHCI_RHPORTSTAT_PRSC _OHCI_MAKEMASK1(20)
+
+#define M_OHCI_RHPORTSTAT_ALLC (M_OHCI_RHPORTSTAT_CSC | \
+ M_OHCI_RHPORTSTAT_PSSC | \
+ M_OHCI_RHPORTSTAT_OCIC | \
+ M_OHCI_RHPORTSTAT_PRSC)
+
+/* *********************************************************************
+ * OHCI Structures
+ ********************************************************************* */
+
+#define beginningof(ptr,type,field) ((type *) (((int) (ptr)) - ((int) ((type *) 0)->field)))
+
+#define OHCI_INTTREE_SIZE 63
+
+#define OHCI_EDPOOL_SIZE 128
+#define OHCI_TDPOOL_SIZE 32
+
+typedef struct ohci_endpoint_s {
+ struct ohci_endpoint_s *ep_next;
+ uint32_t ep_phys;
+ int ep_flags;
+ int ep_mps;
+ int ep_num;
+} ohci_endpoint_t;
+
+typedef struct ohci_transfer_s {
+ void *t_ref;
+ int t_length;
+ struct ohci_transfer_s *t_next;
+} ohci_transfer_t;
+
+typedef struct ohci_softc_s {
+ ohci_endpoint_t *ohci_edtable[OHCI_INTTREE_SIZE];
+ ohci_endpoint_t *ohci_inttable[OHCI_INTTABLE_SIZE];
+ ohci_endpoint_t *ohci_isoc_list;
+ ohci_endpoint_t *ohci_ctl_list;
+ ohci_endpoint_t *ohci_bulk_list;
+ ohci_hcca_t *ohci_hcca;
+ ohci_endpoint_t *ohci_endpoint_pool;
+ ohci_transfer_t *ohci_transfer_pool;
+ ohci_ed_t *ohci_hwedpool;
+ ohci_td_t *ohci_hwtdpool;
+ ohci_endpoint_t *ohci_endpoint_freelist;
+ ohci_transfer_t *ohci_transfer_freelist;
+#ifdef _CFE_
+ physaddr_t ohci_regs;
+#else
+ volatile uint32_t *ohci_regs;
+#endif
+ int ohci_ndp;
+ long ohci_addr;
+ uint32_t ohci_intdisable;
+
+ int ohci_rh_newaddr; /* Address to be set on next status update */
+ int ohci_rh_addr; /* address of root hub */
+ int ohci_rh_conf; /* current configuration # */
+ uint8_t ohci_rh_buf[128]; /* buffer to hold hub responses */
+ uint8_t *ohci_rh_ptr; /* pointer into buffer */
+ int ohci_rh_len; /* remaining bytes to transfer */
+ queue_t ohci_rh_intrq; /* Interrupt request queue */
+ usbbus_t *ohci_bus; /* owning usbbus structure */
+
+} ohci_softc_t;
+
+
+/*
+ * Misc stuff
+ */
+#define OHCI_RESET_DELAY 10
+
+
diff --git a/cfe/cfe/usb/usbchap9.h b/cfe/cfe/usb/usbchap9.h
new file mode 100644
index 0000000..1afd0db
--- /dev/null
+++ b/cfe/cfe/usb/usbchap9.h
@@ -0,0 +1,389 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Chapter 9 definitions File: usbchap9.h
+ *
+ * This module contains definitions from the USB specification,
+ * chapter 9.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+
+#ifndef _USBCHAP9_H_
+#define _USBCHAP9_H_
+
+#define MAXIMUM_USB_STRING_LENGTH 255
+
+/*
+ * values for the bits returned by the USB GET_STATUS command
+ */
+#define USB_GETSTATUS_SELF_POWERED 0x01
+#define USB_GETSTATUS_REMOTE_WAKEUP_ENABLED 0x02
+
+
+#define USB_DEVICE_DESCRIPTOR_TYPE 0x01
+#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02
+#define USB_STRING_DESCRIPTOR_TYPE 0x03
+#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04
+#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05
+#define USB_POWER_DESCRIPTOR_TYPE 0x06
+#define USB_HID_DESCRIPTOR_TYPE 0x21
+#define USB_HUB_DESCRIPTOR_TYPE 0x29
+
+#define USB_DESCRIPTOR_TYPEINDEX(d, i) ((uint16_t)((uint16_t)(d)<<8 | (i)))
+
+/*
+ * Values for bmAttributes field of an
+ * endpoint descriptor
+ */
+
+#define USB_ENDPOINT_TYPE_MASK 0x03
+
+#define USB_ENDPOINT_TYPE_CONTROL 0x00
+#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01
+#define USB_ENDPOINT_TYPE_BULK 0x02
+#define USB_ENDPOINT_TYPE_INTERRUPT 0x03
+
+
+/*
+ * definitions for bits in the bmAttributes field of a
+ * configuration descriptor.
+ */
+#define USB_CONFIG_POWERED_MASK 0xc0
+
+#define USB_CONFIG_BUS_POWERED 0x80
+#define USB_CONFIG_SELF_POWERED 0x40
+#define USB_CONFIG_REMOTE_WAKEUP 0x20
+
+/*
+ * Endpoint direction bit, stored in address
+ */
+
+#define USB_ENDPOINT_DIRECTION_MASK 0x80
+#define USB_ENDPOINT_DIRECTION_IN 0x80 /* bit set means IN */
+
+/*
+ * test direction bit in the bEndpointAddress field of
+ * an endpoint descriptor.
+ */
+#define USB_ENDPOINT_DIR_OUT(addr) (!((addr) & USB_ENDPOINT_DIRECTION_MASK))
+#define USB_ENDPOINT_DIR_IN(addr) ((addr) & USB_ENDPOINT_DIRECTION_MASK)
+
+#define USB_ENDPOINT_ADDRESS(addr) ((addr) & 0x0F)
+
+/*
+ * USB defined request codes
+ * see chapter 9 of the USB 1.0 specifcation for
+ * more information.
+ */
+
+/*
+ * These are the correct values based on the USB 1.0
+ * specification
+ */
+
+#define USB_REQUEST_GET_STATUS 0x00
+#define USB_REQUEST_CLEAR_FEATURE 0x01
+
+#define USB_REQUEST_SET_FEATURE 0x03
+
+#define USB_REQUEST_SET_ADDRESS 0x05
+#define USB_REQUEST_GET_DESCRIPTOR 0x06
+#define USB_REQUEST_SET_DESCRIPTOR 0x07
+#define USB_REQUEST_GET_CONFIGURATION 0x08
+#define USB_REQUEST_SET_CONFIGURATION 0x09
+#define USB_REQUEST_GET_INTERFACE 0x0A
+#define USB_REQUEST_SET_INTERFACE 0x0B
+#define USB_REQUEST_SYNC_FRAME 0x0C
+
+
+/*
+ * defined USB device classes
+ */
+
+
+#define USB_DEVICE_CLASS_RESERVED 0x00
+#define USB_DEVICE_CLASS_AUDIO 0x01
+#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02
+#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03
+#define USB_DEVICE_CLASS_MONITOR 0x04
+#define USB_DEVICE_CLASS_PHYSICAL_INTERFACE 0x05
+#define USB_DEVICE_CLASS_POWER 0x06
+#define USB_DEVICE_CLASS_PRINTER 0x07
+#define USB_DEVICE_CLASS_STORAGE 0x08
+#define USB_DEVICE_CLASS_HUB 0x09
+#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF
+
+/*
+ * USB defined Feature selectors
+ */
+
+#define USB_FEATURE_ENDPOINT_STALL 0x0000
+#define USB_FEATURE_REMOTE_WAKEUP 0x0001
+#define USB_FEATURE_POWER_D0 0x0002
+#define USB_FEATURE_POWER_D1 0x0003
+#define USB_FEATURE_POWER_D2 0x0004
+#define USB_FEATURE_POWER_D3 0x0005
+
+/*
+ * USB Device descriptor.
+ * To reduce problems with compilers trying to optimize
+ * this structure, all the fields are bytes.
+ */
+
+#define USBWORD(x) ((x) & 0xFF),(((x) >> 8) & 0xFF)
+
+#define USB_CONTROL_ENDPOINT_MIN_SIZE 8
+
+typedef struct usb_device_descr_s {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bcdUSBLow,bcdUSBHigh;
+ uint8_t bDeviceClass;
+ uint8_t bDeviceSubClass;
+ uint8_t bDeviceProtocol;
+ uint8_t bMaxPacketSize0;
+ uint8_t idVendorLow,idVendorHigh;
+ uint8_t idProductLow,idProductHigh;
+ uint8_t bcdDeviceLow,bcdDeviceHigh;
+ uint8_t iManufacturer;
+ uint8_t iProduct;
+ uint8_t iSerialNumber;
+ uint8_t bNumConfigurations;
+} usb_device_descr_t;
+
+typedef struct usb_endpoint_descr_s {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bEndpointAddress;
+ uint8_t bmAttributes;
+ uint8_t wMaxPacketSizeLow,wMaxPacketSizeHigh;
+ uint8_t bInterval;
+} usb_endpoint_descr_t;
+
+/*
+ * values for bmAttributes Field in
+ * USB_CONFIGURATION_DESCRIPTOR
+ */
+
+#define CONFIG_BUS_POWERED 0x80
+#define CONFIG_SELF_POWERED 0x40
+#define CONFIG_REMOTE_WAKEUP 0x20
+
+typedef struct usb_config_descr_s {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t wTotalLengthLow,wTotalLengthHigh;
+ uint8_t bNumInterfaces;
+ uint8_t bConfigurationValue;
+ uint8_t iConfiguration;
+ uint8_t bmAttributes;
+ uint8_t MaxPower;
+} usb_config_descr_t;
+
+#define USB_INTERFACE_CLASS_HUB 0x09
+
+typedef struct usb_interface_descr_s {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bInterfaceNumber;
+ uint8_t bAlternateSetting;
+ uint8_t bNumEndpoints;
+ uint8_t bInterfaceClass;
+ uint8_t bInterfaceSubClass;
+ uint8_t bInterfaceProtocol;
+ uint8_t iInterface;
+} usb_interface_descr_t;
+
+typedef struct usb_string_descr_s {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bString[1];
+} usb_string_descr_t;
+
+/*
+ * USB power descriptor added to core specification
+ */
+
+#define USB_SUPPORT_D0_COMMAND 0x01
+#define USB_SUPPORT_D1_COMMAND 0x02
+#define USB_SUPPORT_D2_COMMAND 0x04
+#define USB_SUPPORT_D3_COMMAND 0x08
+
+#define USB_SUPPORT_D1_WAKEUP 0x10
+#define USB_SUPPORT_D2_WAKEUP 0x20
+
+
+typedef struct usb_power_descr_s {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bCapabilitiesFlags;
+ uint16_t EventNotification;
+ uint16_t D1LatencyTime;
+ uint16_t D2LatencyTime;
+ uint16_t D3LatencyTime;
+ uint8_t PowerUnit;
+ uint16_t D0PowerConsumption;
+ uint16_t D1PowerConsumption;
+ uint16_t D2PowerConsumption;
+} usb_power_descr_t;
+
+
+typedef struct usb_common_descr_s {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+} usb_common_descr_t;
+
+typedef struct usb_device_status_s {
+ uint8_t wDeviceStatusLow,wDeviceStatusHigh;
+} usb_device_status_t;
+
+
+/*
+ * Standard USB HUB definitions
+ *
+ * See Chapter 11
+ */
+
+#define USB_HUB_DESCR_SIZE 8
+typedef struct usb_hub_descr_s {
+ uint8_t bDescriptorLength; /* Length of this descriptor */
+ uint8_t bDescriptorType; /* Hub configuration type */
+ uint8_t bNumberOfPorts; /* number of ports on this hub */
+ uint8_t wHubCharacteristicsLow; /* Hub Charateristics */
+ uint8_t wHubCharacteristicsHigh;
+ uint8_t bPowerOnToPowerGood; /* port power on till power good in 2ms */
+ uint8_t bHubControlCurrent; /* max current in mA */
+ /* room for 255 ports power control and removable bitmask */
+ uint8_t bRemoveAndPowerMask[64];
+} usb_hub_descr_t;
+
+#define USB_HUBCHAR_PWR_GANGED 0
+#define USB_HUBCHAR_PWR_IND 1
+#define USB_HUBCHAR_PWR_NONE 2
+
+typedef struct usb_hub_status_s {
+ uint8_t wHubStatusLow,wHubStatusHigh;
+ uint8_t wHubChangeLow,wHubChangeHigh;
+} usb_hub_status_t;
+
+#define USB_PORT_STATUS_CONNECT 0x0001
+#define USB_PORT_STATUS_ENABLED 0x0002
+#define USB_PORT_STATUS_SUSPEND 0x0004
+#define USB_PORT_STATUS_OVERCUR 0x0008
+#define USB_PORT_STATUS_RESET 0x0010
+#define USB_PORT_STATUS_POWER 0x0100
+#define USB_PORT_STATUS_LOWSPD 0x0200
+
+typedef struct usb_port_status_s {
+ uint8_t wPortStatusLow,wPortStatusHigh;
+ uint8_t wPortChangeLow,wPortChangeHigh;
+} usb_port_status_t;
+
+
+#define USB_HUBREQ_GET_STATUS 0
+#define USB_HUBREQ_CLEAR_FEATURE 1
+#define USB_HUBREQ_GET_STATE 2
+#define USB_HUBREQ_SET_FEATURE 3
+#define USB_HUBREQ_GET_DESCRIPTOR 6
+#define USB_HUBREQ_SET_DESCRIPTOR 7
+
+#define USB_HUB_FEATURE_C_LOCAL_POWER 0
+#define USB_HUB_FEATURE_C_OVER_CURRENT 1
+
+#define USB_PORT_FEATURE_CONNECTION 0
+#define USB_PORT_FEATURE_ENABLE 1
+#define USB_PORT_FEATURE_SUSPEND 2
+#define USB_PORT_FEATURE_OVER_CURRENT 3
+#define USB_PORT_FEATURE_RESET 4
+#define USB_PORT_FEATURE_POWER 8
+#define USB_PORT_FEATURE_LOW_SPEED 9
+#define USB_PORT_FEATURE_C_PORT_CONNECTION 16
+#define USB_PORT_FEATURE_C_PORT_ENABLE 17
+#define USB_PORT_FEATURE_C_PORT_SUSPEND 18
+#define USB_PORT_FEATURE_C_PORT_OVER_CURRENT 19
+#define USB_PORT_FEATURE_C_PORT_RESET 20
+
+
+#define GETUSBFIELD(s,f) (((s)->f##Low) | ((s)->f##High << 8))
+#define PUTUSBFIELD(s,f,v) (s)->f##Low = (v & 0xFF); \
+ (s)->f##High = ((v)>>8 & 0xFF)
+
+typedef struct usb_device_request_s {
+ uint8_t bmRequestType;
+ uint8_t bRequest;
+ uint8_t wValueLow,wValueHigh;
+ uint8_t wIndexLow,wIndexHigh;
+ uint8_t wLengthLow,wLengthHigh;
+} usb_device_request_t;
+
+/*
+ * Values for the bmAttributes field of a request
+ */
+#define USBREQ_DIR_IN 0x80
+#define USBREQ_DIR_OUT 0x00
+#define USBREQ_TYPE_STD 0x00
+#define USBREQ_TYPE_CLASS 0x20
+#define USBREQ_TYPE_VENDOR 0x40
+#define USBREQ_TYPE_RSVD 0x60
+#define USBREQ_REC_DEVICE 0x00
+#define USBREQ_REC_INTERFACE 0x01
+#define USBREQ_REC_ENDPOINT 0x02
+#define USBREQ_REC_OTHER 0x03
+
+#define REQCODE(req,dir,type,rec) (((req) << 8) | (dir) | (type) | (rec))
+#define REQSW(req,attr) (((req) << 8) | (attr))
+
+/* *********************************************************************
+ * HID stuff
+ ********************************************************************* */
+
+typedef struct usb_hid_descr_s {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bcdHIDLow,bcdHIDHigh;
+ uint8_t bCountryCode;
+ uint8_t bNumDescriptors;
+ uint8_t bClassDescrType;
+ uint8_t wClassDescrLengthLow,wClassDescrLengthHigh;
+} usb_hid_descr_t;
+
+#endif /* _USBCHAP9_H_ */
diff --git a/cfe/cfe/usb/usbd.c b/cfe/cfe/usb/usbd.c
new file mode 100644
index 0000000..3e77049
--- /dev/null
+++ b/cfe/cfe/usb/usbd.c
@@ -0,0 +1,1215 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * USB device layer File: usbd.c
+ *
+ * This module deals with devices (things connected to USB buses)
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#ifndef _CFE_
+#include <stdio.h>
+#include <time.h>
+#include <memory.h>
+#include <stdint.h>
+#include "usbhack.h"
+#else
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+#include "cfe_timer.h"
+#endif
+
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "usbchap9.h"
+#include "usbd.h"
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+int usb_noisy = 0;
+
+
+/* *********************************************************************
+ * usb_create_pipe(dev,epaddr,mps,flags)
+ *
+ * Create a pipe, causing the corresponding endpoint to
+ * be created in the host controller driver. Pipes form the
+ * basic "handle" for unidirectional communications with a
+ * USB device.
+ *
+ * Input parameters:
+ * dev - device we're talking about
+ * epaddr - endpoint address open, usually from the endpoint
+ * descriptor
+ * mps - maximum packet size understood by the device
+ * flags - flags for this pipe (UP_xxx flags)
+ *
+ * Return value:
+ * <0 if error
+ * 0 if ok
+ ********************************************************************* */
+
+int usb_create_pipe(usbdev_t *dev,int epaddr,int mps,int flags)
+{
+ usbpipe_t *pipe;
+ int pipeidx;
+
+ pipeidx = USB_EPADDR_TO_IDX(epaddr);
+
+ if (dev->ud_pipes[pipeidx] != NULL) {
+ printf("Trying to create a pipe that was already created!\n");
+ return 0;
+ }
+
+ pipe = KMALLOC(sizeof(usbpipe_t),0);
+
+ if (!pipe) return -1;
+
+ pipe->up_flags = flags;
+ pipe->up_num = pipeidx;
+ pipe->up_mps = mps;
+ pipe->up_dev = dev;
+ if (dev->ud_flags & UD_FLAG_LOWSPEED) flags |= UP_TYPE_LOWSPEED;
+ pipe->up_hwendpoint = UBEPTCREATE(dev->ud_bus,
+ dev->ud_address,
+ USB_ENDPOINT_ADDRESS(epaddr),
+ mps,
+ flags);
+
+ dev->ud_pipes[pipeidx] = pipe;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * usb_open_pipe(dev,epdesc)
+ *
+ * Open a pipe given an endpoint descriptor - this is the
+ * normal way pipes get open, since you've just selected a
+ * configuration and have the descriptors handy with all
+ * the information you need.
+ *
+ * Input parameters:
+ * dev - device we're talking to
+ * epdesc - endpoint descriptor
+ *
+ * Return value:
+ * <0 if error
+ * else endpoint/pipe number (from descriptor)
+ ********************************************************************* */
+
+int usb_open_pipe(usbdev_t *dev,usb_endpoint_descr_t *epdesc)
+{
+ int res;
+ int flags = 0;
+
+ if (USB_ENDPOINT_DIR_IN(epdesc->bEndpointAddress)) flags |= UP_TYPE_IN;
+ else flags |= UP_TYPE_OUT;
+
+ switch (epdesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) {
+ case USB_ENDPOINT_TYPE_CONTROL:
+ flags |= UP_TYPE_CONTROL;
+ break;
+ case USB_ENDPOINT_TYPE_ISOCHRONOUS:
+ flags |= UP_TYPE_ISOC;
+ break;
+ case USB_ENDPOINT_TYPE_BULK:
+ flags |= UP_TYPE_BULK;
+ break;
+ case USB_ENDPOINT_TYPE_INTERRUPT:
+ flags |= UP_TYPE_INTR;
+ break;
+ }
+
+ res = usb_create_pipe(dev,
+ epdesc->bEndpointAddress,
+ GETUSBFIELD(epdesc,wMaxPacketSize),
+ flags);
+
+ if (res < 0) return res;
+
+ return epdesc->bEndpointAddress;
+}
+
+
+/* *********************************************************************
+ * usb_destroy_pipe(dev,epaddr)
+ *
+ * Close(destroy) an open pipe and remove endpoint descriptor
+ *
+ * Input parameters:
+ * dev - device we're talking to
+ * epaddr - pipe to close
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void usb_destroy_pipe(usbdev_t *dev,int epaddr)
+{
+ usbpipe_t *pipe;
+ int pipeidx;
+
+ pipeidx = USB_EPADDR_TO_IDX(epaddr);
+
+ pipe = dev->ud_pipes[pipeidx];
+ if (!pipe) return;
+
+ if (dev->ud_pipes[pipeidx]) {
+ UBEPTDELETE(dev->ud_bus,
+ dev->ud_pipes[pipeidx]->up_hwendpoint);
+ }
+
+ KFREE(dev->ud_pipes[pipeidx]);
+ dev->ud_pipes[pipeidx] = NULL;
+}
+
+/* *********************************************************************
+ * usb_destroy_device(dev)
+ *
+ * Delete an entire USB device, closing its pipes and freeing
+ * the device data structure
+ *
+ * Input parameters:
+ * dev - device to destroy
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void usb_destroy_device(usbdev_t *dev)
+{
+ int idx;
+
+ for (idx = 0; idx < UD_MAX_PIPES; idx++) {
+ if (dev->ud_pipes[idx]) {
+ UBEPTDELETE(dev->ud_bus,
+ dev->ud_pipes[idx]->up_hwendpoint);
+ KFREE(dev->ud_pipes[idx]);
+ }
+ }
+
+ dev->ud_bus->ub_devices[dev->ud_address] = NULL;
+
+ KFREE(dev);
+}
+
+
+/* *********************************************************************
+ * usb_create_device(bus,lowspeed)
+ *
+ * Create a new USB device. This device will be set to
+ * communicate on address zero (default address) and will be
+ * ready for basic stuff so we can figure out what it is.
+ * The control pipe will be open, so you can start requesting
+ * descriptors right away.
+ *
+ * Input parameters:
+ * bus - bus to create device on
+ * lowspeed - true if it's a lowspeed device (the hubs tell
+ * us these things)
+ *
+ * Return value:
+ * usb device structure, or NULL
+ ********************************************************************* */
+
+usbdev_t *usb_create_device(usbbus_t *bus,int lowspeed)
+{
+ usbdev_t *dev;
+ int pipeflags;
+
+ /*
+ * Create the device structure.
+ */
+
+ dev = KMALLOC(sizeof(usbdev_t),0);
+ memset(dev,0,sizeof(usbdev_t));
+
+ dev->ud_bus = bus;
+ dev->ud_address = 0; /* default address */
+ dev->ud_parent = NULL;
+ dev->ud_flags = 0;
+
+ /*
+ * Adjust things based on the target device speed
+ */
+
+ pipeflags = UP_TYPE_CONTROL;
+ if (lowspeed) {
+ pipeflags |= UP_TYPE_LOWSPEED;
+ dev->ud_flags |= UD_FLAG_LOWSPEED;
+ }
+
+ /*
+ * Create the control pipe.
+ */
+
+ usb_create_pipe(dev,0,
+ USB_CONTROL_ENDPOINT_MIN_SIZE,
+ pipeflags);
+
+ return dev;
+}
+
+/* *********************************************************************
+ * usb_make_request(dev,epaddr,buf,len,flags)
+ *
+ * Create a template request structure with basic fields
+ * ready to go. A shorthand routine.
+ *
+ * Input parameters:
+ * dev- device we're talking to
+ * epaddr - endpoint address, from usb_open_pipe()
+ * buf,length - user buffer and buffer length
+ * flags - transfer direction, etc. (UR_xxx flags)
+ *
+ * Return value:
+ * usbreq_t pointer, or NULL
+ ********************************************************************* */
+
+usbreq_t *usb_make_request(usbdev_t *dev,int epaddr,uint8_t *buf,int length,int flags)
+{
+ usbreq_t *ur;
+ usbpipe_t *pipe;
+ int pipeidx;
+
+ pipeidx = USB_EPADDR_TO_IDX(epaddr);
+
+ pipe = dev->ud_pipes[pipeidx];
+
+ if (pipe == NULL) return NULL;
+
+ ur = KMALLOC(sizeof(usbreq_t),0);
+ memset(ur,0,sizeof(usbreq_t));
+
+ ur->ur_dev = dev;
+ ur->ur_pipe = pipe;
+ ur->ur_buffer = buf;
+ ur->ur_length = length;
+ ur->ur_flags = flags;
+ ur->ur_callback = NULL;
+
+ return ur;
+
+}
+
+/* *********************************************************************
+ * usb_poll(bus)
+ *
+ * Handle device-driver polling - simply vectors to host controller
+ * driver.
+ *
+ * Input parameters:
+ * bus - bus structure
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void usb_poll(usbbus_t *bus)
+{
+ UBINTR(bus);
+}
+
+/* *********************************************************************
+ * usb_daemon(bus)
+ *
+ * Polls for topology changes and initiates a bus scan if
+ * necessary.
+ *
+ * Input parameters:
+ * bus - bus to watch
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void usb_daemon(usbbus_t *bus)
+{
+ /*
+ * Just see if someone flagged a need for a scan here
+ * and start the bus scan if necessary.
+ *
+ * The actual scanning is a hub function, starting at the
+ * root hub, so the code for that is over there.
+ */
+
+ if (bus->ub_flags & UB_FLG_NEEDSCAN) {
+ bus->ub_flags &= ~UB_FLG_NEEDSCAN;
+ usb_scan(bus);
+ }
+}
+
+/* *********************************************************************
+ * usb_cancel_request(ur)
+ *
+ * Cancel a pending usb transfer request.
+ *
+ * Input parameters:
+ * ur - request to cancel
+ *
+ * Return value:
+ * 0 if ok
+ * else error (could not find request)
+ ********************************************************************* */
+
+int usb_cancel_request(usbreq_t *ur)
+{
+ printf("usb_cancel_request is not implemented.\n");
+ return 0;
+}
+
+/* *********************************************************************
+ * usb_free_request(ur)
+ *
+ * Return a transfer request to the free pool.
+ *
+ * Input parameters:
+ * ur - request to return
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void usb_free_request(usbreq_t *ur)
+{
+ if (ur->ur_inprogress) {
+ printf("Yow! Tried to free a request that was in progress!\n");
+ return;
+ }
+ KFREE(ur);
+}
+
+/* *********************************************************************
+ * usb_delay_ms(bus,ms)
+ *
+ * Wait a while, calling the polling routine as we go.
+ *
+ * Input parameters:
+ * bus - bus we're talking to
+ * ms - how long to wait
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+void usb_delay_ms(usbbus_t *bus,int ms)
+{
+#ifdef _CFE_
+ cfe_sleep(1+((ms*CFE_HZ)/1000));
+#else
+ mydelay(ms);
+#endif
+}
+
+/* *********************************************************************
+ * usb_queue_request(ur)
+ *
+ * Call the transfer handler in the host controller driver to
+ * set up a transfer descriptor
+ *
+ * Input parameters:
+ * ur - request to queue
+ *
+ * Return value:
+ * 0 if ok
+ * else error
+ ********************************************************************* */
+
+int usb_queue_request(usbreq_t *ur)
+{
+ int res;
+
+ ur->ur_inprogress = 1;
+ ur->ur_xferred = 0;
+ res = UBXFER(ur->ur_dev->ud_bus,
+ ur->ur_pipe->up_hwendpoint,
+ ur);
+ return res;
+}
+
+/* *********************************************************************
+ * usb_wait_request(ur)
+ *
+ * Wait until a request completes, calling the polling routine
+ * as we wait.
+ *
+ * Input parameters:
+ * ur - request to wait for
+ *
+ * Return value:
+ * request status
+ ********************************************************************* */
+
+int usb_wait_request(usbreq_t *ur)
+{
+ while ((volatile int) (ur->ur_inprogress)) {
+ usb_poll(ur->ur_dev->ud_bus);
+ }
+
+ return ur->ur_status;
+}
+
+/* *********************************************************************
+ * usb_sync_request(ur)
+ *
+ * Synchronous request - call usb_queue and then usb_wait
+ *
+ * Input parameters:
+ * ur - request to submit
+ *
+ * Return value:
+ * status of request
+ ********************************************************************* */
+
+int usb_sync_request(usbreq_t *ur)
+{
+ usb_queue_request(ur);
+ return usb_wait_request(ur);
+}
+
+/* *********************************************************************
+ * usb_simple_request(dev,reqtype,bRequest,wValue,wIndex)
+ *
+ * Handle a simple USB control pipe request. These are OUT
+ * requests with no data phase.
+ *
+ * Input parameters:
+ * dev - device we're talking to
+ * reqtype - request type (bmRequestType) for descriptor
+ * wValue - wValue for descriptor
+ * wIndex - wIndex for descriptor
+ *
+ * Return value:
+ * 0 if ok
+ * else error
+ ********************************************************************* */
+
+int usb_simple_request(usbdev_t *dev,uint8_t reqtype,int bRequest,int wValue,int wIndex)
+{
+#if 0
+ uint8_t *requestbuf;
+ usb_device_request_t *req;
+ usbreq_t *ur;
+ int res;
+
+ requestbuf = KMALLOC(32,0);
+
+ req = (usb_device_request_t *) requestbuf;
+
+ req->bmRequestType = reqtype;
+ req->bRequest = bRequest;
+ PUTUSBFIELD(req,wValue,wValue);
+ PUTUSBFIELD(req,wIndex,wIndex);
+ PUTUSBFIELD(req,wLength,0);
+
+ if (usb_noisy > 1) printf("Request: ");
+ ur = usb_make_request(dev,0,requestbuf,sizeof(usb_device_request_t),UR_FLAG_SETUP);
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+
+ if (res == 4) { /* STALL on control pipe */
+ if (usb_noisy > 1) printf("STALL\n");
+ usb_clear_stall(dev,dev->ud_pipes[0]->up_num);
+ return -1;
+ }
+
+ res = ur->ur_xferred;
+ if (usb_noisy > 1) printf("Result %d\n",res);
+
+ if (usb_noisy > 1) printf("Status: ");
+ ur = usb_make_request(dev,0,requestbuf,0,UR_FLAG_STATUS_IN);
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+ if (usb_noisy > 1) printf("Result %d\n",res);
+
+ if (res == 4) { /* STALL */
+ if (usb_noisy > 1) printf("STALL\n");
+ usb_clear_stall(dev,dev->ud_pipes[0]->up_num);
+ return -1;
+ }
+
+ KFREE(requestbuf);
+
+ return 0;
+#else
+ return usb_std_request(dev,reqtype,bRequest,wValue,wIndex,NULL,0);
+#endif
+
+}
+
+
+/* *********************************************************************
+ * usb_set_configuration(dev,config)
+ *
+ * Set the current configuration for a USB device.
+ *
+ * Input parameters:
+ * dev - device we're talking to
+ * config - bConfigValue for the device
+ *
+ * Return value:
+ * request status
+ ********************************************************************* */
+
+int usb_set_configuration(usbdev_t *dev,int config)
+{
+ int res;
+
+ res = usb_simple_request(dev,0x00,USB_REQUEST_SET_CONFIGURATION,config,0);
+
+ return res;
+}
+
+
+/* *********************************************************************
+ * usb_new_address(bus)
+ *
+ * Return the next available address for the specified bus
+ *
+ * Input parameters:
+ * bus - bus to assign an address for
+ *
+ * Return value:
+ * new address, <0 if error
+ ********************************************************************* */
+
+int usb_new_address(usbbus_t *bus)
+{
+ int idx;
+
+ for (idx = 1; idx < USB_MAX_DEVICES; idx++) {
+ if (bus->ub_devices[idx] == NULL) return idx;
+ }
+
+ return -1;
+}
+
+/* *********************************************************************
+ * usb_set_address(dev,address)
+ *
+ * Set the address of a device. This also puts the device
+ * in the master device table for the bus and reconfigures the
+ * address of the control pipe.
+ *
+ * Input parameters:
+ * dev - device we're talking to
+ * address - new address (1..127)
+ *
+ * Return value:
+ * request status
+ ********************************************************************* */
+
+int usb_set_address(usbdev_t *dev,int address)
+{
+ int res;
+ int idx;
+ usbpipe_t *pipe;
+
+ res = usb_simple_request(dev,0x00,USB_REQUEST_SET_ADDRESS,address,0);
+
+ if (res == 0) {
+ dev->ud_bus->ub_devices[address] = dev;
+ dev->ud_address = address;
+ for (idx = 0; idx < UD_MAX_PIPES; idx++) {
+ pipe = dev->ud_pipes[idx];
+ if (pipe && pipe->up_hwendpoint) {
+ UBEPTSETADDR(dev->ud_bus,pipe->up_hwendpoint,address);
+ }
+ }
+ }
+
+ return res;
+}
+
+/* *********************************************************************
+ * usb_set_ep0mps(dev,mps)
+ *
+ * Set the maximum packet size of endpoint zero (mucks with the
+ * endpoint in the host controller)
+ *
+ * Input parameters:
+ * dev - device we're talking to
+ * mps - max packet size for endpoint zero
+ *
+ * Return value:
+ * request status
+ ********************************************************************* */
+
+int usb_set_ep0mps(usbdev_t *dev,int mps)
+{
+ usbpipe_t *pipe;
+
+ pipe = dev->ud_pipes[0];
+ if (pipe && pipe->up_hwendpoint) {
+ UBEPTSETMPS(dev->ud_bus,pipe->up_hwendpoint,mps);
+ }
+ if (pipe) {
+ pipe->up_mps = mps;
+ }
+
+ return 0;
+}
+
+/* *********************************************************************
+ * usb_clear_stall(dev,epaddr)
+ *
+ * Clear a stall condition on the specified pipe
+ *
+ * Input parameters:
+ * dev - device we're talking to
+ * epaddr - endpoint address
+ *
+ * Return value:
+ * 0 if ok
+ * else error
+ ********************************************************************* */
+int usb_clear_stall(usbdev_t *dev,int epaddr)
+{
+ uint8_t *requestbuf;
+ usb_device_request_t *req;
+ usbreq_t *ur;
+ int res;
+ int pipeidx;
+
+ /*
+ * Clear the stall in the hardware.
+ */
+
+ pipeidx = USB_EPADDR_TO_IDX(epaddr);
+
+ UBEPTCLEARTOGGLE(dev->ud_bus,dev->ud_pipes[pipeidx]->up_hwendpoint);
+
+ /*
+ * Do the "clear stall" request. Note that we should do this
+ * without calling usb_simple_request, since usb_simple_request
+ * may itself stall.
+ */
+
+ requestbuf = KMALLOC(32,0);
+
+ req = (usb_device_request_t *) requestbuf;
+
+ req->bmRequestType = 0x02;
+ req->bRequest = USB_REQUEST_CLEAR_FEATURE;
+ PUTUSBFIELD(req,wValue,0); /* ENDPOINT_HALT */
+ PUTUSBFIELD(req,wIndex,epaddr);
+ PUTUSBFIELD(req,wLength,0);
+
+ ur = usb_make_request(dev,0,requestbuf,
+ sizeof(usb_device_request_t),
+ UR_FLAG_SETUP);
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+ ur = usb_make_request(dev,0,requestbuf,0,UR_FLAG_STATUS_IN);
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+
+ KFREE(requestbuf);
+
+ return 0;
+}
+
+
+
+/* *********************************************************************
+ * usb_std_request(dev,bmRequestType,bRequest,wValue,
+ * wIndex,buffer,length)
+ *
+ * Do a standard control request on the control pipe,
+ * with the appropriate setup, data, and status phases.
+ *
+ * Input parameters:
+ * dev - dev we're talking to
+ * bmRequestType,bRequest,wValue,wIndex - fields for the
+ * USB request structure
+ * buffer - user buffer
+ * length - length of user buffer
+ *
+ * Return value:
+ * number of bytes transferred
+ ********************************************************************* */
+
+int usb_std_request(usbdev_t *dev,uint8_t bmRequestType,
+ uint8_t bRequest,uint16_t wValue,
+ uint16_t wIndex,uint8_t *buffer,int length)
+{
+ usbpipe_t *pipe = dev->ud_pipes[0];
+ usbreq_t *ur;
+ int res;
+ usb_device_request_t *req;
+ uint8_t *databuf = NULL;
+
+ req = KMALLOC(32,0);
+
+ if ((buffer != NULL) && (length !=0)) {
+ databuf = KMALLOC(length,0);
+ if (!(bmRequestType & USBREQ_DIR_IN)) {
+ memcpy(databuf,buffer,length);
+ }
+ else {
+ memset(databuf,0,length);
+ }
+ }
+
+ req->bmRequestType = bmRequestType;
+ req->bRequest = bRequest;
+ PUTUSBFIELD(req,wValue,wValue);
+ PUTUSBFIELD(req,wIndex,wIndex);
+ PUTUSBFIELD(req,wLength,length);
+
+ ur = usb_make_request(dev,0,(uint8_t *)req,sizeof(usb_device_request_t),UR_FLAG_SETUP);
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+
+ if (length != 0) {
+ if (bmRequestType & USBREQ_DIR_IN) {
+ ur = usb_make_request(dev,0,databuf,length,UR_FLAG_IN);
+ }
+ else {
+ ur = usb_make_request(dev,0,databuf,length,UR_FLAG_OUT);
+ }
+
+ res = usb_sync_request(ur);
+
+ if (res == 4) { /* STALL */
+ usb_clear_stall(dev,pipe->up_num);
+ usb_free_request(ur);
+ if (databuf) KFREE(databuf);
+ KFREE(req);
+ return 0;
+ }
+
+ length = ur->ur_xferred;
+ usb_free_request(ur);
+ }
+
+ if ((length != 0) && (databuf != NULL) && (bmRequestType & USBREQ_DIR_IN)) {
+ memcpy(buffer,databuf,length);
+ }
+
+ if (bmRequestType & USBREQ_DIR_IN) {
+ ur = usb_make_request(dev,0,(uint8_t *)req,0,UR_FLAG_STATUS_OUT);
+ }
+ else {
+ ur = usb_make_request(dev,0,(uint8_t *)req,0,UR_FLAG_STATUS_IN);
+ }
+
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+
+ if (res == 4) { /* STALL */
+ usb_clear_stall(dev,pipe->up_num);
+ if (databuf) KFREE(databuf);
+ KFREE(req);
+ return 0;
+ }
+
+ if (databuf) KFREE(databuf);
+ KFREE(req);
+
+ return length;
+}
+
+
+
+
+/* *********************************************************************
+ * usb_get_descriptor(dev,reqtype,dsctype,dscidx,respbuf,buflen)
+ *
+ * Request a descriptor from the device.
+ *
+ * Input parameters:
+ * dev - device we're talking to
+ * reqtype - bmRequestType field for descriptor we want
+ * dsctype - descriptor type we want
+ * dscidx - index of descriptor we want (often zero)
+ * respbuf - response buffer
+ * buflen - length of response buffer
+ *
+ * Return value:
+ * number of bytes transferred
+ ********************************************************************* */
+
+int usb_get_descriptor(usbdev_t *dev,uint8_t reqtype,int dsctype,int dscidx,
+ uint8_t *respbuf,int buflen)
+{
+ return usb_std_request(dev,
+ reqtype,USB_REQUEST_GET_DESCRIPTOR,
+ USB_DESCRIPTOR_TYPEINDEX(dsctype,dscidx),
+ 0,
+ respbuf,buflen);
+}
+
+/* *********************************************************************
+ * usb_get_string(dev,id,buf,maxlen)
+ *
+ * Request a string from the device, converting it from
+ * unicode to ascii (brutally).
+ *
+ * Input parameters:
+ * dev - device we're talking to
+ * id - string ID
+ * buf - buffer to receive string (null terminated)
+ * maxlen - length of buffer
+ *
+ * Return value:
+ * number of characters in returned string
+ ********************************************************************* */
+
+int usb_get_string(usbdev_t *dev,int id,char *buf,int maxlen)
+{
+ int amtcopy;
+ uint8_t *respbuf;
+ int idx;
+ usb_string_descr_t *sdscr;
+
+ respbuf = KMALLOC(maxlen*2+2,0);
+ sdscr = (usb_string_descr_t *) respbuf;
+
+ /*
+ * First time just get the header of the descriptor so we can
+ * get the string length
+ */
+
+ amtcopy = usb_get_descriptor(dev,USBREQ_DIR_IN,USB_STRING_DESCRIPTOR_TYPE,id,
+ respbuf,2);
+
+ /*
+ * now do it again to get the whole string.
+ */
+
+ if (maxlen > sdscr->bLength) maxlen = sdscr->bLength;
+
+ amtcopy = usb_get_descriptor(dev,USBREQ_DIR_IN,USB_STRING_DESCRIPTOR_TYPE,id,
+ respbuf,maxlen);
+
+ *buf = '\0';
+ amtcopy = sdscr->bLength - 2;
+ if (amtcopy <= 0) return amtcopy;
+
+ for (idx = 0; idx < amtcopy; idx+=2) {
+ *buf++ = sdscr->bString[idx];
+ }
+
+ *buf = '\0';
+
+ KFREE(respbuf);
+
+ return amtcopy;
+}
+
+
+
+/* *********************************************************************
+ * usb_get_device_descriptor(dev,dscr,smallflg)
+ *
+ * Request the device descriptor for the device. This is often
+ * the first descriptor requested, so it needs to be done in
+ * stages so we can find out how big the control pipe is.
+ *
+ * Input parameters:
+ * dev - device we're talking to
+ * dscr - pointer to buffer to receive descriptor
+ * smallflg - TRUE to request just 8 bytes.
+ *
+ * Return value:
+ * number of bytes copied
+ ********************************************************************* */
+
+int usb_get_device_descriptor(usbdev_t *dev,usb_device_descr_t *dscr,int smallflg)
+{
+ int res;
+ uint8_t *respbuf;
+ int amtcopy;
+
+ /*
+ * Smallflg truncates the request 8 bytes. We need to do this for
+ * the very first transaction to a USB device in order to determine
+ * the size of its control pipe. Bad things will happen if you
+ * try to retrieve more data than the control pipe will hold.
+ *
+ * So, be conservative at first and get the first 8 bytes of the
+ * descriptor. Byte 7 is bMaxPacketSize0, the size of the control
+ * pipe. Then you can go back and submit a bigger request for
+ * everything else.
+ */
+
+ amtcopy = smallflg ? USB_CONTROL_ENDPOINT_MIN_SIZE : sizeof(usb_device_descr_t);
+
+ respbuf = KMALLOC(64,0);
+ res = usb_get_descriptor(dev,USBREQ_DIR_IN,USB_DEVICE_DESCRIPTOR_TYPE,0,respbuf,amtcopy);
+ memcpy(dscr,respbuf,amtcopy);
+ KFREE(respbuf);
+ return res;
+
+}
+
+/* *********************************************************************
+ * usb_get_config_descriptor(dev,dscr,idx,maxlen)
+ *
+ * Request the configuration descriptor from the device.
+ *
+ * Input parameters:
+ * dev - device we're talking to
+ * dscr - descriptor buffer (receives data from device)
+ * idx - index of config we want (usually zero)
+ * maxlen - total size of buffer to receive descriptor
+ *
+ * Return value:
+ * number of bytes copied
+ ********************************************************************* */
+
+int usb_get_config_descriptor(usbdev_t *dev,usb_config_descr_t *dscr,int idx,int maxlen)
+{
+ int res;
+ uint8_t *respbuf;
+
+ respbuf = KMALLOC(maxlen,0);
+ res = usb_get_descriptor(dev,USBREQ_DIR_IN,
+ USB_CONFIGURATION_DESCRIPTOR_TYPE,idx,
+ respbuf,maxlen);
+ memcpy(dscr,respbuf,maxlen);
+ KFREE(respbuf);
+ return res;
+
+}
+
+
+
+/* *********************************************************************
+ * usb_get_device_status(dev,status)
+ *
+ * Request status from the device (status descriptor)
+ *
+ * Input parameters:
+ * dev - device we're talking to
+ * status - receives device_status structure
+ *
+ * Return value:
+ * number of bytes returned
+ ********************************************************************* */
+
+int usb_get_device_status(usbdev_t *dev,usb_device_status_t *status)
+{
+ return usb_std_request(dev,
+ USBREQ_DIR_IN,
+ 0,
+ 0,
+ 0,
+ (uint8_t *) status,
+ sizeof(usb_device_status_t));
+}
+
+
+/* *********************************************************************
+ * usb_complete_request(ur,status)
+ *
+ * Called when a usb request completes - pass status to
+ * caller and call the callback if there is one.
+ *
+ * Input parameters:
+ * ur - usbreq_t to complete
+ * status - completion status
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void usb_complete_request(usbreq_t *ur,int status)
+{
+ ur->ur_status = status;
+ ur->ur_inprogress = 0;
+ if (ur->ur_callback) (*(ur->ur_callback))(ur);
+}
+
+
+/* *********************************************************************
+ * usb_initroot(bus)
+ *
+ * Initialize the root hub for the bus - we need to do this
+ * each time a bus is configured.
+ *
+ * Input parameters:
+ * bus - bus to initialize
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void usb_initroot(usbbus_t *bus)
+{
+ usbdev_t *dev;
+ usb_driver_t *drv;
+ int addr;
+ int res;
+ uint8_t *buf;
+ int len;
+ usb_config_descr_t cfgdescr;
+
+ /*
+ * Create a device for the root hub.
+ */
+
+ dev = usb_create_device(bus,0);
+ bus->ub_roothub = dev;
+
+ /*
+ * Get the device descriptor. Make sure it's a hub.
+ */
+
+ res = usb_get_device_descriptor(dev,&(dev->ud_devdescr),TRUE);
+
+ if (dev->ud_devdescr.bDeviceClass != USB_DEVICE_CLASS_HUB) {
+ printf("Error! Root device is not a hub!\n");
+ return;
+ }
+
+ /*
+ * Set up the max packet size for the control endpoint,
+ * then get the rest of the descriptor.
+ */
+
+ usb_set_ep0mps(dev,dev->ud_devdescr.bMaxPacketSize0);
+ res = usb_get_device_descriptor(dev,&(dev->ud_devdescr),FALSE);
+
+ /*
+ * Obtain a new address and set the address of the
+ * root hub to this address.
+ */
+
+ addr = usb_new_address(dev->ud_bus);
+ res = usb_set_address(dev,addr);
+
+ /*
+ * Get the configuration descriptor and all the
+ * associated interface and endpoint descriptors.
+ */
+
+ res = usb_get_config_descriptor(dev,&cfgdescr,0,
+ sizeof(usb_config_descr_t));
+ if (res != sizeof(usb_config_descr_t)) {
+ printf("[a]usb_get_config_descriptor returns %d\n",res);
+ }
+
+ len = GETUSBFIELD(&cfgdescr,wTotalLength);
+ buf = KMALLOC(len,0);
+
+ res = usb_get_config_descriptor(dev,(usb_config_descr_t *)buf,0,len);
+ if (res != len) {
+ printf("[b]usb_get_config_descriptor returns %d\n",res);
+ }
+
+ dev->ud_cfgdescr = (usb_config_descr_t *) buf;
+
+ /*
+ * Select the configuration. Not really needed for our poor
+ * imitation root hub, but it's the right thing to do.
+ */
+
+ usb_set_configuration(dev,cfgdescr.bConfigurationValue);
+
+ /*
+ * Find the driver for this. It had better be the hub
+ * driver.
+ */
+
+ drv = usb_find_driver(dev);
+
+ /*
+ * Call the attach method.
+ */
+
+ (*(drv->udrv_attach))(dev,drv);
+
+ /*
+ * Hub should now be operational.
+ */
+
+}
+
+
+/* *********************************************************************
+ * usb_find_cfg_descr(dev,dtype,idx)
+ *
+ * Find a configuration descriptor - we retrieved all the config
+ * descriptors during discovery, this lets us dig out the one
+ * we want.
+ *
+ * Input parameters:
+ * dev - device we are talking to
+ * dtype - descriptor type to find
+ * idx - index of descriptor if there's more than one
+ *
+ * Return value:
+ * pointer to descriptor or NULL if not found
+ ********************************************************************* */
+
+void *usb_find_cfg_descr(usbdev_t *dev,int dtype,int idx)
+{
+ uint8_t *endptr;
+ uint8_t *ptr;
+ usb_config_descr_t *cfgdscr;
+
+ if (dev->ud_cfgdescr == NULL) return NULL;
+
+ ptr = (uint8_t *) dev->ud_cfgdescr;
+ endptr = ptr + GETUSBFIELD((dev->ud_cfgdescr),wTotalLength);
+
+ while (ptr < endptr) {
+
+ cfgdscr = (usb_config_descr_t *) ptr;
+
+ if (cfgdscr->bDescriptorType == dtype) {
+ if (idx == 0) return (void *) ptr;
+ else idx--;
+ }
+
+ ptr += cfgdscr->bLength;
+
+ }
+
+ return NULL;
+}
diff --git a/cfe/cfe/usb/usbd.h b/cfe/cfe/usb/usbd.h
new file mode 100644
index 0000000..73fde86
--- /dev/null
+++ b/cfe/cfe/usb/usbd.h
@@ -0,0 +1,308 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * USB Device Layer definitions File: usbd.h
+ *
+ * Definitions for the USB device layer.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifndef _PHYSADDR_T_DEFINED_
+#include "lib_physio.h"
+#endif
+
+#include "usbchap9.h"
+
+
+/* *********************************************************************
+ * Forward declarations and opaque types
+ ********************************************************************* */
+
+typedef struct usb_hc_s usb_hc_t;
+typedef struct usb_ept_s usb_ept_t;
+typedef struct usb_hcdrv_s usb_hcdrv_t;
+typedef struct usbdev_s usbdev_t;
+typedef struct usb_driver_s usb_driver_t;
+
+/* *********************************************************************
+ * USB Bus structure - one of these per host controller
+ ********************************************************************* */
+
+#define USB_MAX_DEVICES 128
+
+typedef struct usbbus_s {
+ struct usbbus_s *ub_next; /* link to other buses */
+ usb_hc_t *ub_hwsoftc; /* bus driver softc */
+ usb_hcdrv_t *ub_hwdisp; /* bus driver dispatch */
+ usbdev_t *ub_roothub; /* root hub device */
+ usbdev_t *ub_devices[USB_MAX_DEVICES]; /* pointers to each device, idx by address */
+ unsigned int ub_flags; /* flag bits */
+ int ub_num; /* bus number */
+} usbbus_t;
+
+#define UB_FLG_NEEDSCAN 1 /* some device on bus needs scanning */
+
+/* *********************************************************************
+ * USB Pipe structure - one of these per unidirectional channel
+ * to an endpoint on a USB device
+ ********************************************************************* */
+
+#define UP_TYPE_CONTROL 1
+#define UP_TYPE_BULK 2
+#define UP_TYPE_INTR 4
+#define UP_TYPE_ISOC 8
+
+#define UP_TYPE_IN 128
+#define UP_TYPE_OUT 256
+
+#define UP_TYPE_LOWSPEED 16
+
+typedef struct usbpipe_s {
+ usb_ept_t *up_hwendpoint; /* OHCI-specific endpoint pointer */
+ usbdev_t *up_dev; /* our device info */
+ int up_num; /* pipe number */
+ int up_mps; /* max packet size */
+ int up_flags;
+} usbpipe_t;
+
+/* *********************************************************************
+ * USB device structure - one per device attached to the USB
+ * This is the basic structure applications will use to
+ * refer to a device.
+ ********************************************************************* */
+
+#define UD_FLAG_HUB 0x0001 /* this is a hub device */
+#define UD_FLAG_ROOTHUB 0x0002 /* this is a root hub device */
+#define UD_FLAG_LOWSPEED 0x0008 /* this is a lowspeed device */
+
+#define UD_MAX_PIPES 32
+#define USB_EPADDR_TO_IDX(addr) ((((addr)&0x80) >> 3) | ((addr) & 0x0F))
+//#define USB_EPADDR_TO_IDX(addr) USB_ENDPOINT_ADDRESS(addr)
+//#define UD_MAX_PIPES 16
+
+struct usbdev_s {
+ usb_driver_t *ud_drv; /* Driver's methods */
+ usbbus_t *ud_bus; /* owning bus */
+ int ud_address; /* USB address */
+ usbpipe_t *ud_pipes[UD_MAX_PIPES]; /* pipes, 0 is the control pipe */
+ struct usbdev_s *ud_parent; /* used for hubs */
+ int ud_flags;
+ void *ud_private; /* private data for device driver */
+ usb_device_descr_t ud_devdescr; /* device descriptor */
+ usb_config_descr_t *ud_cfgdescr; /* config, interface, and ep descrs */
+};
+
+
+/* *********************************************************************
+ * USB Request - basic structure to describe an in-progress
+ * I/O request. It associates buses, pipes, and buffers
+ * together.
+ ********************************************************************* */
+
+
+#define UR_FLAG_SYNC 0x8000
+
+#define UR_FLAG_SETUP 0x0001
+#define UR_FLAG_IN 0x0002
+#define UR_FLAG_OUT 0x0004
+#define UR_FLAG_STATUS_IN 0x0008 /* status phase of a control WRITE */
+#define UR_FLAG_STATUS_OUT 0x0010 /* status phase of a control READ */
+#define UR_FLAG_SHORTOK 0x0020 /* short transfers are ok */
+
+
+typedef struct usbreq_s {
+ queue_t ur_qblock;
+
+ /*
+ * pointers to our device and pipe
+ */
+
+ usbdev_t *ur_dev;
+ usbpipe_t *ur_pipe;
+
+ /*
+ * stuff to keep track of the data we transfer
+ */
+
+ uint8_t *ur_buffer;
+ int ur_length;
+ int ur_xferred;
+ int ur_status;
+ int ur_flags;
+
+ /*
+ * Stuff needed for the callback
+ */
+ void *ur_ref;
+ int ur_inprogress;
+ int (*ur_callback)(struct usbreq_s *req);
+
+ /*
+ * For use inside the ohci driver
+ */
+ void *ur_tdqueue;
+ int ur_tdcount;
+} usbreq_t;
+
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+int usb_create_pipe(usbdev_t *dev,int pipenum,int mps,int flags);
+void usb_destroy_pipe(usbdev_t *dev,int pipenum);
+int usb_set_address(usbdev_t *dev,int addr);
+usbdev_t *usb_create_device(usbbus_t *bus,int lowspeed);
+void usb_destroy_device(usbdev_t *dev);
+usbreq_t *usb_make_request(usbdev_t *dev,int pipenum,uint8_t *buf,int length,int flags);
+void usb_poll(usbbus_t *bus);
+void usb_daemon(usbbus_t *bus);
+int usb_cancel_request(usbreq_t *ur);
+void usb_free_request(usbreq_t *ur);
+int usb_queue_request(usbreq_t *ur);
+int usb_wait_request(usbreq_t *ur);
+int usb_sync_request(usbreq_t *ur);
+int usb_get_descriptor(usbdev_t *dev,uint8_t reqtype,int dsctype,int dscidx,uint8_t *buffer,int buflen);
+int usb_get_config_descriptor(usbdev_t *dev,usb_config_descr_t *dscr,int idx,int maxlen);
+int usb_get_device_status(usbdev_t *dev,usb_device_status_t *status);
+int usb_set_configuration(usbdev_t *dev,int config);
+int usb_open_pipe(usbdev_t *dev,usb_endpoint_descr_t *epdesc);
+int usb_simple_request(usbdev_t *dev,uint8_t reqtype,int bRequest,int wValue,int wIndex);
+void usb_complete_request(usbreq_t *ur,int status);
+int usb_get_device_descriptor(usbdev_t *dev,usb_device_descr_t *dscr,int smallflg);
+int usb_set_ep0mps(usbdev_t *dev,int mps);
+int usb_new_address(usbbus_t *bus);
+int usb_get_string(usbdev_t *dev,int id,char *buf,int maxlen);
+int usb_std_request(usbdev_t *dev,uint8_t bmRequestType,
+ uint8_t bRequest,uint16_t wValue,
+ uint16_t wIndex,uint8_t *buffer,int length);
+void *usb_find_cfg_descr(usbdev_t *dev,int dtype,int idx);
+void usb_delay_ms(usbbus_t *bus,int ms);
+int usb_clear_stall(usbdev_t *dev,int pipe);
+
+void usb_scan(usbbus_t *bus);
+void usbhub_map_tree(usbbus_t *bus,int (*func)(usbdev_t *dev,void *arg),void *arg);
+void usbhub_dumpbus(usbbus_t *bus,uint32_t verbose);
+
+void usb_initroot(usbbus_t *bus);
+
+
+/* *********************************************************************
+ * Host Controller Driver
+ * Methods for abstracting the USB host controller from the
+ * rest of the goop.
+ ********************************************************************* */
+
+struct usb_hcdrv_s {
+ usbbus_t * (*hcdrv_create)(physaddr_t regaddr);
+ void (*hcdrv_delete)(usbbus_t *);
+ int (*hcdrv_start)(usbbus_t *);
+ void (*hcdrv_stop)(usbbus_t *);
+ int (*hcdrv_intr)(usbbus_t *);
+ usb_ept_t * (*hcdrv_ept_create)(usbbus_t *,int usbaddr,int eptnum,int mps,int flags);
+ void (*hcdrv_ept_delete)(usbbus_t *,usb_ept_t *);
+ void (*hcdrv_ept_setmps)(usbbus_t *,usb_ept_t *,int mps);
+ void (*hcdrv_ept_setaddr)(usbbus_t *,usb_ept_t *,int addr);
+ void (*hcdrv_ept_cleartoggle)(usbbus_t *,usb_ept_t *);
+ int (*hcdrv_xfer)(usbbus_t *,usb_ept_t *uept,usbreq_t *ur);
+};
+
+#define UBCREATE(driver,addr) (*((driver)->hcdrv_create))(addr)
+#define UBDELETE(bus) (*((bus)->ub_hwdisp->hcdrv_delete))(bus)
+#define UBSTART(bus) (*((bus)->ub_hwdisp->hcdrv_start))(bus)
+#define UBSTOP(bus) (*((bus)->ub_hwdisp->hcdrv_stop))(bus)
+#define UBINTR(bus) (*((bus)->ub_hwdisp->hcdrv_intr))(bus)
+#define UBEPTCREATE(bus,addr,num,mps,flags) (*((bus)->ub_hwdisp->hcdrv_ept_create))(bus,addr,num,mps,flags)
+#define UBEPTDELETE(bus,ept) (*((bus)->ub_hwdisp->hcdrv_ept_delete))(bus,ept)
+#define UBEPTSETMPS(bus,ept,mps) (*((bus)->ub_hwdisp->hcdrv_ept_setmps))(bus,ept,mps)
+#define UBEPTSETADDR(bus,ept,addr) (*((bus)->ub_hwdisp->hcdrv_ept_setaddr))(bus,ept,addr)
+#define UBEPTCLEARTOGGLE(bus,ept) (*((bus)->ub_hwdisp->hcdrv_ept_cleartoggle))(bus,ept)
+#define UBXFER(bus,ept,xfer) (*((bus)->ub_hwdisp->hcdrv_xfer))(bus,ept,xfer)
+
+/* *********************************************************************
+ * Devices - methods for abstracting things that _use_ USB
+ * (devices you can plug into the USB) - the entry points
+ * here are basically just for device discovery, since the top half
+ * of the actual driver will be device-specific.
+ ********************************************************************* */
+
+struct usb_driver_s {
+ char *udrv_name;
+ int (*udrv_attach)(usbdev_t *,usb_driver_t *);
+ int (*udrv_detach)(usbdev_t *);
+};
+
+typedef struct usb_drvlist_s {
+ int udl_class;
+ int udl_vendor;
+ int udl_product;
+ usb_driver_t *udl_disp;
+} usb_drvlist_t;
+
+extern usb_driver_t *usb_find_driver(usbdev_t *dev);
+
+#define CLASS_ANY -1
+#define VENDOR_ANY -1
+#define PRODUCT_ANY -1
+
+void mydelay(int x);
+
+#define IS_HUB(dev) ((dev)->ud_devdescr.bDeviceClass == USB_DEVICE_CLASS_HUB)
+
+/* *********************************************************************
+ * Error codes
+ ********************************************************************* */
+
+#define USBD_ERR_OK 0 /* Request ok */
+#define USBD_ERR_STALLED -1 /* Endpoint is stalled */
+#define USBD_ERR_IOERROR -2 /* I/O error */
+#define USBD_ERR_HWERROR -3 /* Hardware failure */
+#define USBD_ERR_CANCELED -4 /* Request canceled */
+#define USBD_ERR_NOMEM -5 /* Out of memory */
+#define USBD_ERR_TIMEOUT -6 /* Request timeout */
+
+/* *********************************************************************
+ * Debug routines
+ ********************************************************************* */
+
+void usb_dbg_dumpportstatus(int port,usb_port_status_t *portstatus,int level);
+void usb_dbg_dumpdescriptors(usbdev_t *dev,uint8_t *ptr,int len);
+void usb_dbg_dumpcfgdescr(usbdev_t *dev);
+void usb_dbg_dumpeptdescr(usb_endpoint_descr_t * epdscr);
diff --git a/cfe/cfe/usb/usbdebug.c b/cfe/cfe/usb/usbdebug.c
new file mode 100644
index 0000000..14ed866
--- /dev/null
+++ b/cfe/cfe/usb/usbdebug.c
@@ -0,0 +1,307 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * USB debugging code File: usbdebug.c
+ *
+ * This module contains debug code for USB.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#ifndef _CFE_
+#include <stdio.h>
+#include <time.h>
+#include <memory.h>
+#include <stdint.h>
+#include "usbhack.h"
+#else
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+#endif
+
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "usbchap9.h"
+#include "usbd.h"
+
+
+void usb_dbg_dumpportstatus(int port,usb_port_status_t *portstatus,int level)
+{
+ int idx;
+ uint16_t x;
+
+ for (idx = 0; idx < level; idx++) printf(" ");
+ printf("PORT %d STATUS\n",port);
+
+ for (idx = 0; idx < level; idx++) printf(" ");
+ x = GETUSBFIELD((portstatus),wPortStatus);
+ printf("wPortStatus = %04X ",x);
+ if (x & 1) printf("DevicePresent ");
+ if (x & 2) printf("Enabled ");
+ if (x & 4) printf("Suspend ");
+ if (x & 8) printf("OverCurrent ");
+ if (x & 16) printf("InReset ");
+ if (x & 256) printf("Powered ");
+ if (x & 512) printf("LowSpeed ");
+ printf("\n");
+ for (idx = 0; idx < level; idx++) printf(" ");
+ x = GETUSBFIELD((portstatus),wPortChange);
+ printf("wPortChange = %04X ",x);
+ if (x & 1) printf("ConnectChange ");
+ if (x & 2) printf("EnableChange ");
+ if (x & 4) printf("SuspendChange ");
+ if (x & 8) printf("OverCurrentChange ");
+ if (x & 16) printf("ResetChange ");
+ printf("\n");
+}
+
+void usb_dbg_dumpeptdescr(usb_endpoint_descr_t * epdscr)
+{
+ printf("---------------------------------------------------\n");
+ printf("ENDPOINT DESCRIPTOR\n");
+
+ printf("bLength = %d\n",epdscr->bLength);
+ printf("bDescriptorType = %d\n",epdscr->bDescriptorType);
+ printf("bEndpointAddr = %02X\n",epdscr->bEndpointAddress);
+ printf("bmAttrbutes = %02X\n",epdscr->bmAttributes);
+ printf("wMaxPacketSize = %d\n",GETUSBFIELD(epdscr,wMaxPacketSize));
+ printf("bInterval = %d\n",epdscr->bInterval);
+}
+
+static char *getstringmaybe(usbdev_t *dev,int string)
+{
+ static char buf[256];
+
+ return "";
+
+ if (string == 0) {
+ strcpy(buf,"none");
+ return buf;
+ }
+
+ memset(buf,0,sizeof(buf));
+
+ usb_get_string(dev,string,buf,sizeof(buf));
+
+ return buf;
+}
+
+void usb_dbg_dumpdescriptors(usbdev_t *dev,uint8_t *ptr,int len)
+{
+ uint8_t *endptr;
+ usb_config_descr_t *cfgdscr;
+ usb_interface_descr_t *ifdscr;
+ usb_device_descr_t *devdscr;
+ usb_endpoint_descr_t *epdscr;
+ usb_hid_descr_t *hiddscr;
+ usb_hub_descr_t *hubdscr;
+ static char *eptattribs[4] = {"Control","Isoc","Bulk","Interrupt"};
+ int idx;
+
+ endptr = ptr + len;
+
+ while (ptr < endptr) {
+
+ cfgdscr = (usb_config_descr_t *) ptr;
+
+ switch (cfgdscr->bDescriptorType) {
+ case USB_DEVICE_DESCRIPTOR_TYPE:
+ devdscr = (usb_device_descr_t *) ptr;
+ printf("---------------------------------------------------\n");
+ printf("DEVICE DESCRIPTOR\n");
+ printf("bLength = %d\n",devdscr->bLength);
+ printf("bDescriptorType = %d\n",devdscr->bDescriptorType);
+ printf("bcdUSB = %04X\n",GETUSBFIELD(devdscr,bcdUSB));
+ printf("bDeviceClass = %d\n",devdscr->bDeviceClass);
+ printf("bDeviceSubClass = %d\n",devdscr->bDeviceSubClass);
+ printf("bDeviceProtocol = %d\n",devdscr->bDeviceProtocol);
+ printf("bMaxPktSize0 = %d\n",devdscr->bMaxPacketSize0);
+ if (endptr-ptr <= 8) break;
+ printf("idVendor = %04X (%d)\n",
+ GETUSBFIELD(devdscr,idVendor),
+ GETUSBFIELD(devdscr,idVendor));
+ printf("idProduct = %04X (%d)\n",
+ GETUSBFIELD(devdscr,idProduct),
+ GETUSBFIELD(devdscr,idProduct));
+ printf("bcdDevice = %04X\n",GETUSBFIELD(devdscr,bcdDevice));
+ printf("iManufacturer = %d (%s)\n",
+ devdscr->iManufacturer,
+ getstringmaybe(dev,devdscr->iManufacturer));
+ printf("iProduct = %d (%s)\n",
+ devdscr->iProduct,
+ getstringmaybe(dev,devdscr->iProduct));
+ printf("iSerialNumber = %d (%s)\n",
+ devdscr->iSerialNumber,
+ getstringmaybe(dev,devdscr->iSerialNumber));
+ printf("bNumConfigs = %d\n",devdscr->bNumConfigurations);
+ break;
+ case USB_CONFIGURATION_DESCRIPTOR_TYPE:
+
+ cfgdscr = (usb_config_descr_t *) ptr;
+ printf("---------------------------------------------------\n");
+ printf("CONFIG DESCRIPTOR\n");
+
+ printf("bLength = %d\n",cfgdscr->bLength);
+ printf("bDescriptorType = %d\n",cfgdscr->bDescriptorType);
+ printf("wTotalLength = %d\n",GETUSBFIELD(cfgdscr,wTotalLength));
+ printf("bNumInterfaces = %d\n",cfgdscr->bNumInterfaces);
+ printf("bConfigValue = %d\n",cfgdscr->bConfigurationValue);
+ printf("iConfiguration = %d (%s)\n",
+ cfgdscr->iConfiguration,
+ getstringmaybe(dev,cfgdscr->iConfiguration));
+ printf("bmAttributes = %02X\n",cfgdscr->bmAttributes);
+ printf("MaxPower = %d (%dma)\n",cfgdscr->MaxPower,cfgdscr->MaxPower*2);
+ break;
+
+ case USB_INTERFACE_DESCRIPTOR_TYPE:
+ printf("---------------------------------------------------\n");
+ printf("INTERFACE DESCRIPTOR\n");
+
+ ifdscr = (usb_interface_descr_t *) ptr;
+
+ printf("bLength = %d\n",ifdscr->bLength);
+ printf("bDescriptorType = %d\n",ifdscr->bDescriptorType);
+ printf("bInterfaceNum = %d\n",ifdscr->bInterfaceNumber);
+ printf("bAlternateSet = %d\n",ifdscr->bAlternateSetting);
+ printf("bNumEndpoints = %d\n",ifdscr->bNumEndpoints);
+ printf("bInterfaceClass = %d\n",ifdscr->bInterfaceClass);
+ printf("bInterSubClass = %d\n",ifdscr->bInterfaceSubClass);
+ printf("bInterfaceProto = %d\n",ifdscr->bInterfaceProtocol);
+ printf("iInterface = %d (%s)\n",
+ ifdscr->iInterface,
+ getstringmaybe(dev,ifdscr->iInterface));
+ break;
+
+ case USB_ENDPOINT_DESCRIPTOR_TYPE:
+ printf("---------------------------------------------------\n");
+ printf("ENDPOINT DESCRIPTOR\n");
+
+ epdscr = (usb_endpoint_descr_t *) ptr;
+
+ printf("bLength = %d\n",epdscr->bLength);
+ printf("bDescriptorType = %d\n",epdscr->bDescriptorType);
+ printf("bEndpointAddr = %02X (%d,%s)\n",
+ epdscr->bEndpointAddress,
+ epdscr->bEndpointAddress & 0x0F,
+ (epdscr->bEndpointAddress & USB_ENDPOINT_DIRECTION_IN) ? "IN" : "OUT"
+ );
+ printf("bmAttrbutes = %02X (%s)\n",
+ epdscr->bmAttributes,
+ eptattribs[epdscr->bmAttributes&3]);
+ printf("wMaxPacketSize = %d\n",GETUSBFIELD(epdscr,wMaxPacketSize));
+ printf("bInterval = %d\n",epdscr->bInterval);
+ break;
+
+ case USB_HID_DESCRIPTOR_TYPE:
+ printf("---------------------------------------------------\n");
+ printf("HID DESCRIPTOR\n");
+
+ hiddscr = (usb_hid_descr_t *) ptr;
+
+ printf("bLength = %d\n",hiddscr->bLength);
+ printf("bDescriptorType = %d\n",hiddscr->bDescriptorType);
+ printf("bcdHID = %04X\n",GETUSBFIELD(hiddscr,bcdHID));
+ printf("bCountryCode = %d\n",hiddscr->bCountryCode);
+ printf("bNumDescriptors = %d\n",hiddscr->bNumDescriptors);
+ printf("bClassDescrType = %d\n",hiddscr->bClassDescrType);
+ printf("wClassDescrLen = %d\n",GETUSBFIELD(hiddscr,wClassDescrLength));
+ break;
+
+ case USB_HUB_DESCRIPTOR_TYPE:
+ printf("---------------------------------------------------\n");
+ printf("HUB DESCRIPTOR\n");
+
+ hubdscr = (usb_hub_descr_t *) ptr;
+
+ printf("bLength = %d\n",hubdscr->bDescriptorLength);
+ printf("bDescriptorType = %d\n",hubdscr->bDescriptorType);
+ printf("bNumberOfPorts = %d\n",hubdscr->bNumberOfPorts);
+ printf("wHubCharacters = %04X\n",GETUSBFIELD(hubdscr,wHubCharacteristics));
+ printf("bPowerOnToPwrGd = %d\n",hubdscr->bPowerOnToPowerGood);
+ printf("bHubControlCurr = %d (ma)\n",hubdscr->bHubControlCurrent);
+ printf("bRemPwerMask[0] = %02X\n",hubdscr->bRemoveAndPowerMask[0]);
+
+ break;
+
+ default:
+ printf("---------------------------------------------------\n");
+ printf("UNKNOWN DESCRIPTOR\n");
+ printf("bLength = %d\n",cfgdscr->bLength);
+ printf("bDescriptorType = %d\n",cfgdscr->bDescriptorType);
+ printf("Data Bytes = ");
+ for (idx = 0; idx < cfgdscr->bLength; idx++) {
+ printf("%02X ",ptr[idx]);
+ }
+ printf("\n");
+
+ }
+
+ ptr += cfgdscr->bLength;
+
+ }
+}
+
+
+void usb_dbg_dumpcfgdescr(usbdev_t *dev)
+{
+ uint8_t buffer[512];
+ int res;
+ int len;
+ usb_config_descr_t *cfgdscr;
+
+ memset(buffer,0,sizeof(buffer));
+
+ cfgdscr = (usb_config_descr_t *) &buffer[0];
+
+ res = usb_get_config_descriptor(dev,cfgdscr,0,sizeof(usb_config_descr_t));
+ if (res != sizeof(usb_config_descr_t)) {
+ printf("[a]usb_get_config_descriptor returns %d\n",res);
+ }
+
+ len = GETUSBFIELD(cfgdscr,wTotalLength);
+
+ res = usb_get_config_descriptor(dev,cfgdscr,0,len);
+ if (res != len) {
+ printf("[b]usb_get_config_descriptor returns %d\n",res);
+ }
+
+ usb_dbg_dumpdescriptors(dev,&buffer[0],res);
+}
diff --git a/cfe/cfe/usb/usbdevs.c b/cfe/cfe/usb/usbdevs.c
new file mode 100644
index 0000000..53a0754
--- /dev/null
+++ b/cfe/cfe/usb/usbdevs.c
@@ -0,0 +1,168 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * USB Driver List File: usbdevs.c
+ *
+ * This module contains a table of supported USB devices and
+ * the routines to look up appropriate drivers given
+ * USB product, device, and class codes.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifndef _CFE_
+#include <stdio.h>
+#include <memory.h>
+#include <stdint.h>
+#include "usbhack.h"
+#else
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+#endif
+
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "usbchap9.h"
+#include "usbd.h"
+
+/* *********************************************************************
+ * The list of drivers we support. If you add more drivers,
+ * list them here.
+ ********************************************************************* */
+
+extern usb_driver_t usbhub_driver;
+extern usb_driver_t usbhid_driver;
+extern usb_driver_t usbmass_driver;
+extern usb_driver_t usbserial_driver;
+extern usb_driver_t usbeth_driver;
+
+usb_drvlist_t usb_drivers[] = {
+
+ /*
+ * Hub driver
+ */
+
+ {USB_DEVICE_CLASS_HUB, VENDOR_ANY, PRODUCT_ANY, &usbhub_driver},
+
+ /*
+ * Keyboards and mice
+ */
+
+ {USB_DEVICE_CLASS_HUMAN_INTERFACE, VENDOR_ANY,PRODUCT_ANY, &usbhid_driver},
+
+ /*
+ * Mass storage devices
+ */
+
+ {USB_DEVICE_CLASS_STORAGE, VENDOR_ANY, PRODUCT_ANY, &usbmass_driver},
+
+ /*
+ * Serial ports
+ */
+
+ {USB_DEVICE_CLASS_VENDOR_SPECIFIC,0x557,0x2008,&usbserial_driver},
+
+ /*
+ * Ethernet Adapters
+ */
+
+ {USB_DEVICE_CLASS_VENDOR_SPECIFIC,0x506,0x4601,&usbeth_driver}, /* 3Com */
+ {USB_DEVICE_CLASS_VENDOR_SPECIFIC,0x66b,0x2202,&usbeth_driver}, /* Linksys */
+ {USB_DEVICE_CLASS_VENDOR_SPECIFIC,0x66b,0x2203,&usbeth_driver}, /* Linksys */
+ {USB_DEVICE_CLASS_VENDOR_SPECIFIC,0x66b,0x2204,&usbeth_driver}, /* Linksys */
+ {USB_DEVICE_CLASS_VENDOR_SPECIFIC,0x66b,0x2206,&usbeth_driver}, /* Linksys */
+ {USB_DEVICE_CLASS_VENDOR_SPECIFIC,0x66b,0x400b,&usbeth_driver}, /* Linksys */
+ {USB_DEVICE_CLASS_VENDOR_SPECIFIC,0x66b,0x200c,&usbeth_driver}, /* Linksys */
+ {USB_DEVICE_CLASS_RESERVED,0xbda,0x8150,&usbeth_driver}, /* Realtek */
+ {USB_DEVICE_CLASS_VENDOR_SPECIFIC,0x423,0x000a,&usbeth_driver}, /* CATC */
+ {USB_DEVICE_CLASS_VENDOR_SPECIFIC,0x423,0x000c,&usbeth_driver}, /* Belkin */
+
+ {0,0,0,NULL}
+};
+
+
+/* *********************************************************************
+ * usb_find_driver(class,vendor,product)
+ *
+ * Find a suitable device driver to handle the specified
+ * class, vendor, or product.
+ *
+ * Input parameters:
+ * devdescr - device descriptor
+ *
+ * Return value:
+ * pointer to device driver or NULL
+ ********************************************************************* */
+
+usb_driver_t *usb_find_driver(usbdev_t *dev)
+{
+ usb_device_descr_t *devdescr;
+ usb_interface_descr_t *ifdescr;
+ usb_drvlist_t *list;
+ int dclass,vendor,product;
+
+ devdescr = &(dev->ud_devdescr);
+
+ dclass = devdescr->bDeviceClass;
+ if (dclass == 0) {
+ ifdescr = usb_find_cfg_descr(dev,USB_INTERFACE_DESCRIPTOR_TYPE,0);
+ if (ifdescr) dclass = ifdescr->bInterfaceClass;
+ }
+
+ vendor = (int) GETUSBFIELD(devdescr,idVendor);
+ product = (int) GETUSBFIELD(devdescr,idProduct);
+
+ printf("USB: Locating Class %02X Vendor %04X Product %04X: ",dclass,vendor,product);
+
+ list = usb_drivers;
+ while (list->udl_disp) {
+ if (((list->udl_class == dclass) || (list->udl_class == CLASS_ANY)) &&
+ ((list->udl_vendor == vendor) || (list->udl_vendor == VENDOR_ANY)) &&
+ ((list->udl_product == product) || (list->udl_product == PRODUCT_ANY))) {
+ printf("%s\n",list->udl_disp->udrv_name);
+ return list->udl_disp;
+ }
+ list++;
+ }
+
+ printf("Not found.\n");
+
+ return NULL;
+}
diff --git a/cfe/cfe/usb/usbeth.c b/cfe/cfe/usb/usbeth.c
new file mode 100644
index 0000000..bc5aeb0
--- /dev/null
+++ b/cfe/cfe/usb/usbeth.c
@@ -0,0 +1,850 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * USB Ethernet File: usbeth.c
+ *
+ * Driver for USB Ethernet devices.
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+/* *********************************************************************
+ * USB-Ethernet driver - CFE Network Layer Interfaces
+ * NOTE: Some of the device setup for the Admtek & Realtek devices
+ * was derived from reverse engineering! So these interfaces
+ * assume proper device operation.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_ioctl.h"
+#include "cfe_timer.h"
+#include "cfe_device.h"
+#include "cfe_devfuncs.h"
+#include "cfe_error.h"
+
+#include "usbd.h"
+#include "usbeth.h"
+
+#if 0
+#define USBETH_TRACE( x, y ... ) xprintf( x, ##y )
+#else
+#define USBETH_TRACE( x, y ... )
+#endif
+
+#define FAIL -1
+
+static int Dev_cnt = 0;
+
+
+/******************************************************************************
+ Debug functions
+******************************************************************************/
+
+//#define DATA_DUMP
+#ifdef DATA_DUMP
+static void hexdump( unsigned char * src, int srclen, int rowlen, int rows )
+{
+ unsigned char * rowptr;
+ unsigned char * srcstp;
+ unsigned char * byteptr;
+
+ srcstp = src + srclen;
+
+ for( rowptr = src; rowptr < src + rowlen * rows; rowptr += rowlen ) {
+ for( byteptr = rowptr; byteptr < rowptr + rowlen && byteptr < srcstp; byteptr++ ) {
+ xprintf( "%2X ", *byteptr );
+ }
+ xprintf( "\n" );
+ }
+ xprintf( "\n" );
+}
+#endif
+
+
+/* *********************************************************************
+ * Interface functions for USB-Ethernet adapters
+ ********************************************************************* */
+
+enum { PEGASUS, PEGASUS_II, NETMATE, REALTEK };
+enum { VEN_NONE, _3_COM, LINKSYS, LINKSYS_10, LINKSYS_100,
+ CATC_NM, BELKIN_CATC, LINKSYS_100M };
+static char * VENDOR_NAMES[] =
+{
+ "?", "3-COM", "LinkSys", "LinkSys-10TX", "LinkSys-100TX",
+ "CATC-Netmate", "Belkin/CATC", "Linksys-100M", "Yikes!"
+};
+
+typedef struct usbeth_softc_s
+{
+ usbdev_t *dev;
+ int bulk_inpipe;
+ int bulk_outpipe;
+ int dev_id;
+ int ven_code;
+ int embed_tx_len;
+ uint8_t mac_addr[6];
+ usbreq_t *rx_ur;
+ uint8_t rxbuf[1600]; //artbitrary but enough for ethernet packet
+} usbeth_softc_t;
+
+
+/* **************************************
+ * CATC I/F Functions
+ ************************************** */
+
+#if 0
+static int catc_get_reg( usbdev_t *dev, int16_t reg, uint8_t *val )
+{
+ return usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_IN),
+ CATC_GET_REG, 0, reg, val, 1 );
+}
+#endif
+
+static int catc_set_reg( usbdev_t *dev, int16_t reg, int16_t val )
+{
+ return usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_OUT),
+ CATC_SET_REG, val, reg, NULL, 0 );
+}
+
+static int catc_set_mem( usbdev_t *dev, int16_t addr,
+ uint8_t *data, int16_t len )
+{
+ return usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_OUT),
+ CATC_SET_MEM, 0, addr, data, len );
+}
+
+static int catc_get_mac_addr( usbdev_t *dev, uint8_t *mac_addr )
+{
+ int status;
+
+ status = usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_IN),
+ CATC_GET_MAC_ADDR, 0, 0, mac_addr, 6 );
+ return( status );
+}
+
+static void catc_init_device( usbeth_softc_t * softc )
+{
+ usbdev_t *dev = softc->dev;
+ unsigned char *mcast_tbl;
+
+ usb_std_request( dev, (USBREQ_TYPE_STD | USBREQ_REC_INTERFACE),
+ USB_REQUEST_SET_INTERFACE,
+ 1, //alt setting 1
+ 0, NULL, 0 );
+
+ catc_set_reg(dev, CATC_TX_BUF_CNT_REG, 0x04 );
+ catc_set_reg(dev, CATC_RX_BUF_CNT_REG, 0x10 );
+ catc_set_reg(dev, CATC_ADV_OP_MODES_REG, 0x01 );
+ catc_set_reg(dev, CATC_LED_CTRL_REG, 0x08 );
+
+ /* Enable broadcast rx via bit in mutlicast table */
+ mcast_tbl = KMALLOC(64, 0);
+ memset( mcast_tbl, 0, 64 );
+ mcast_tbl[31] = 0x80; //i.e. broadcast bit
+ catc_set_mem( dev, CATC_MCAST_TBL_ADDR, mcast_tbl, 64 );
+ KFREE(mcast_tbl);
+
+ //Read the adapter's MAC addr
+ catc_get_mac_addr( dev, softc->mac_addr );
+}
+
+static void catc_close_device( usbdev_t *dev )
+{
+ // Now disable adapter from receiving packets
+ catc_set_reg( dev, CATC_ETH_CTRL_REG, 0 );
+}
+
+static void catc_open_device( usbeth_softc_t * softc )
+{
+ int i;
+
+ for(i = 0; i < 6; ++i)
+ catc_set_reg( softc->dev, (CATC_ETH_ADDR_0_REG - i), softc->mac_addr[i] );
+
+ // Now enable adapter to receive packets
+ catc_set_reg( softc->dev, CATC_ETH_CTRL_REG, 0x09 );
+}
+
+/* **************************************
+ * PEGASUS I/F Functions
+ ************************************** */
+
+static int peg_get_reg( usbdev_t *dev, int16_t reg, uint8_t *val, int16_t len )
+{
+ return usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_IN),
+ PEG_GET_REG, 0, reg, val, len );
+}
+
+static int peg_set_reg( usbdev_t *dev, int16_t reg, int16_t val )
+{
+ unsigned char data = (uint8_t) val & 0xff;
+
+ return usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_OUT),
+ PEG_SET_REG, val, reg, &data, 1 );
+}
+
+static int peg_set_regs( usbdev_t *dev, int16_t reg, int8_t *vals, int16_t len )
+{
+ return usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_OUT),
+ PEG_SET_REG, 0, reg, vals, len );
+}
+
+static int peg_get_eep_word( usbdev_t *dev, int16_t ofs, uint8_t *val )
+{
+ int status=0, tries=20;
+ uint8_t data[2];
+
+ if( peg_set_reg( dev, PEG_EEPROM_CTL_REG, 0 ) == FAIL )
+ return FAIL;
+ if( peg_set_reg( dev, PEG_EEPROM_OFS_REG, ofs ) == FAIL )
+ return FAIL;
+ if( peg_set_reg( dev, PEG_EEPROM_CTL_REG, 0x02 ) == FAIL ) //read
+ return FAIL;
+ while( --tries )
+ {
+ if( peg_get_reg( dev, PEG_EEPROM_CTL_REG, data, 1 ) == FAIL )
+ return FAIL;
+ if( data[0] & 0x04 )
+ break; //eeprom data ready
+ }
+ if( !tries )
+ {
+ xprintf( "Pegasus Eeprom read failed!\n" );
+ return FAIL;
+ }
+ if( peg_get_reg( dev, PEG_EEPROM_DATA_REG, data, 2 ) == FAIL )
+ return FAIL;
+ val[0] = data[0];
+ val[1] = data[1];
+
+ return( status );
+}
+
+static int peg_get_mac_addr( usbdev_t *dev, uint8_t *mac_addr )
+{
+ int i, status;
+
+ for( i = 0; i < 3; ++i )
+ {
+ status = peg_get_eep_word( dev, i, &mac_addr[i*2] );
+ }
+ return( status );
+}
+
+static void peg_init_phy( usbdev_t *dev )
+{ //needed for earlier versions (before Rev B) of the USB-100TX adapters
+ static uint8_t phy_magic_wr[] = { 0, 4, 0, 0x1b };
+ static uint8_t read_status[] = { 0, 0, 0, 1 };
+ uint8_t data[4];
+
+ //reset the MAC ans set up GPIOs
+ peg_set_reg( dev, PEG_ETH_CTL1_REG, 0x08 );
+ peg_get_reg( dev, PEG_ETH_CTL1_REG, data, 1 );
+
+ //do following steps to enable link activitiy LED
+ peg_set_reg( dev, PEG_GPIO1_REG, 0x26 );
+ peg_set_reg( dev, PEG_GPIO0_REG, 0x24 );
+ peg_set_reg( dev, PEG_GPIO0_REG, 0x26 );
+
+ //do following set of steps to enable LINK LED
+ memcpy( data, phy_magic_wr, 4 );
+ peg_set_regs( dev, PEG_PHY_ADDR_REG, data, 4); //set up for magic word
+ peg_set_reg( dev, PEG_PHY_CTRL_REG, (0x1b|PHY_WRITE) );
+ peg_get_reg( dev, PEG_PHY_CTRL_REG, data, 1 ); //read status of write
+ memcpy( data, read_status, 4 );
+ peg_set_regs( dev, PEG_PHY_ADDR_REG, data, 4); //set up for phy status reg
+ peg_set_reg( dev, PEG_PHY_CTRL_REG, (1|PHY_READ) );
+ peg_get_reg( dev, PEG_PHY_CTRL_REG, data, 1 ); //read status of read
+ peg_get_reg( dev, PEG_PHY_DATA_REG, data, 2 ); //read status regs
+}
+
+static void peg_init_device( usbeth_softc_t * softc )
+{
+ usbdev_t *dev = softc->dev;
+
+ if( softc->dev_id == PEGASUS_II )
+ peg_set_reg( dev, PEG_INT_PHY_REG, 0x02 ); //enable internal PHY
+ else
+ peg_init_phy( dev );
+
+ //Read the adapter's MAC addr
+ peg_get_mac_addr( dev, softc->mac_addr );
+}
+
+static void peg_close_device( usbdev_t *dev )
+{
+ //Now disable adapter from receiving or transmitting packets
+ peg_set_reg( dev, PEG_ETH_CTL1_REG, 0 );
+}
+
+static void peg_open_device( usbeth_softc_t * softc )
+{
+ usbdev_t *dev = softc->dev;
+
+ //Now setup adapter's receiver with MAC address
+ peg_set_regs( dev, PEG_MAC_ADDR_0_REG, softc->mac_addr, 6 );
+
+ //Now enable adapter to receive and transmit packets
+ peg_set_reg( dev, PEG_ETH_CTL0_REG, 0xc1 );
+ peg_set_reg( dev, PEG_ETH_CTL1_REG, 0x30 );
+}
+
+/* **************************************
+ * REALTEK I/F Functions
+ ************************************** */
+
+//
+// ********** NOT FULLY WORKING YET!!!!!!!!!! ***************
+//
+
+static int rtek_get_reg( usbdev_t *dev, int16_t reg, uint8_t *val, int16_t len )
+{
+ return usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_IN),
+ RTEK_REG_ACCESS, reg, 0, val, len );
+}
+
+static int rtek_set_reg( usbdev_t *dev, int16_t reg, int16_t val )
+{
+ unsigned char data = (uint8_t) val & 0xff;
+
+ return usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_OUT),
+ RTEK_REG_ACCESS, reg, 0, &data, 1 );
+}
+
+static int rtek_get_mac_addr( usbdev_t *dev, uint8_t *mac_addr )
+{
+ int status;
+
+ status = rtek_get_reg( dev, RTEK_MAC_REG, mac_addr, 6 );
+
+ return( status );
+}
+
+static void rtek_init_device( usbeth_softc_t * softc )
+{
+ int i;
+ usbdev_t *dev = softc->dev;
+ uint8_t val;
+
+ //Reset the adapter
+ rtek_set_reg( dev, RTEK_CMD_REG, RTEK_RESET );
+ for( i = 0; i < 10; ++i )
+ {
+ rtek_get_reg( dev, RTEK_CMD_REG, &val, 1 );
+ if( !(val & RTEK_RESET) )
+ break;
+ usb_delay_ms( NULL, 1 );
+ }
+
+ //autoload the internal registers
+ rtek_set_reg( dev, RTEK_CMD_REG, RTEK_AUTOLOAD );
+ for( i = 0; i < 50; ++i )
+ {
+ rtek_get_reg( dev, RTEK_CMD_REG, &val, 1 );
+ if( !(val & RTEK_AUTOLOAD) )
+ break;
+ usb_delay_ms( NULL, 1 );
+ }
+
+ //Read the adapter's MAC addr
+ rtek_get_mac_addr( dev, softc->mac_addr );
+}
+
+static void rtek_close_device( usbdev_t *dev )
+{
+ //Now disable adapter from receiving or transmitting packets
+ rtek_set_reg( dev, RTEK_CMD_REG, 0 );
+}
+
+static void rtek_open_device( usbeth_softc_t * softc )
+{
+ //accept broadcast & own packets
+ rtek_set_reg( softc->dev, RTEK_RXCFG_REG, 0x0c );
+
+ //Now enable adapter to receive and transmit packets
+ rtek_set_reg( softc->dev, RTEK_CMD_REG, 0x0c );
+}
+
+//*********************** USB-ETH I/F Functions ****************************
+
+static const int ID_TBL[] =
+{
+ 0x0506, 0x4601, PEGASUS_II, _3_COM, //3-Com
+ 0x066b, 0x2202, PEGASUS_II, LINKSYS_10, //LinkSys
+ 0x066b, 0x2203, PEGASUS, LINKSYS_100,
+ 0x066b, 0x2204, PEGASUS, LINKSYS_100,
+ 0x066b, 0x2206, PEGASUS, LINKSYS,
+ 0x066b, 0x400b, PEGASUS_II, LINKSYS_10,
+ 0x066b, 0x200c, PEGASUS_II, LINKSYS_10,
+ 0x0bda, 0x8150, REALTEK, LINKSYS_100M,
+ 0x0423, 0x000a, NETMATE, CATC_NM, //CATC (Netmate I)
+ 0x0423, 0x000c, NETMATE, BELKIN_CATC, //Belkin & CATC (Netmate II)
+ -1
+};
+
+static int usbeth_init_device( usbeth_softc_t * softc )
+{
+ int i;
+ usb_device_descr_t dev_desc;
+ uint16_t vendor_id, device_id;
+ const int *ptr=ID_TBL;
+
+ //find out which device is connected
+ usb_get_device_descriptor( softc->dev, &dev_desc, 0 );
+ vendor_id = (dev_desc.idVendorHigh << 8) + dev_desc.idVendorLow;
+ device_id = (dev_desc.idProductHigh << 8) + dev_desc.idProductLow;
+ xprintf( "USB device: vendor id %04x, device id %04x\n",
+ vendor_id, device_id );
+
+ while( *ptr != -1 )
+ {
+ if( (vendor_id == ptr[0]) && (device_id == ptr[1]) )
+ {
+ softc->dev_id = ptr[2];
+ softc->ven_code = ptr[3];
+ break;
+ }
+ ptr += 4;
+ }
+ if( *ptr == -1 )
+ {
+ xprintf( "Unrecognized USB-Ethernet device\n" );
+ return -1;
+ }
+
+ //init the adapter
+ if( softc->dev_id == NETMATE )
+ {
+ catc_init_device( softc );
+ softc->embed_tx_len = 1;
+ }
+ else
+ {
+ if( softc->dev_id == REALTEK )
+ {
+ rtek_init_device( softc );
+ softc->embed_tx_len = 0;
+ }
+ else
+ {
+ peg_init_device( softc );
+ softc->embed_tx_len = 1;
+ }
+ }
+
+ //display adapter info
+ xprintf( "%s USB-Ethernet Adapter (", VENDOR_NAMES[softc->ven_code] );
+ for( i = 0; i < 6; ++i )
+ xprintf( "%02x%s", softc->mac_addr[i], (i == 5) ? ")\n" : ":" );
+
+ return 0;
+}
+
+static int usbeth_get_dev_addr( usbeth_softc_t * softc, uint8_t *mac_addr )
+{
+ memcpy( mac_addr, softc->mac_addr, 6 );
+ return 0;
+}
+
+static void usbeth_queue_rx( usbeth_softc_t * softc )
+{
+ softc->rx_ur = usb_make_request(softc->dev, softc->bulk_inpipe,
+ softc->rxbuf, sizeof(softc->rxbuf),
+ (UR_FLAG_IN | UR_FLAG_SHORTOK));
+ usb_queue_request(softc->rx_ur);
+}
+
+static void usbeth_close_device( usbeth_softc_t * softc )
+{
+ if( softc->dev_id == NETMATE )
+ catc_close_device( softc->dev );
+ else if( softc->dev_id == REALTEK )
+ rtek_close_device( softc->dev );
+ else
+ peg_close_device( softc->dev );
+}
+
+static void usbeth_open_device( usbeth_softc_t * softc )
+{
+ if( softc->dev_id == NETMATE )
+ catc_open_device( softc );
+ else if( softc->dev_id == REALTEK )
+ rtek_open_device( softc );
+ else
+ peg_open_device( softc );
+
+ //kick start the receive
+ usbeth_queue_rx( softc );
+}
+
+static int usbeth_data_rx( usbeth_softc_t * softc )
+{
+ usb_poll(softc->dev->ud_bus);
+ return( !softc->rx_ur->ur_inprogress );
+}
+
+static int usbeth_get_eth_frame( usbeth_softc_t * softc, unsigned char * buf )
+{
+ int len = 0;
+
+ if( !softc->rx_ur->ur_inprogress )
+ {
+ len = softc->rx_ur->ur_xferred;
+ memcpy( buf, softc->rxbuf, len );
+ usb_free_request(softc->rx_ur);
+ usbeth_queue_rx( softc );
+ }
+ else
+ xprintf( "Bulk data is not available yet!\n" );
+
+ return( len );
+}
+
+static int usbeth_send_eth_frame( usbeth_softc_t * softc, unsigned char * buf, int len )
+{
+ usbreq_t *ur;
+ int txlen = len;
+ unsigned char * txbuf;
+
+ if(softc->embed_tx_len)
+ {
+ txbuf = KMALLOC((len+2), 0);
+ txbuf[0] = txlen & 0xff;
+ txbuf[1] = (txlen >> 8) & 0xff; //1st two bytes...little endian
+ memcpy( &txbuf[2], buf, txlen );
+ txlen += 2;
+ }
+ else
+ {
+ if( softc->dev_id == REALTEK )
+ {
+ //Now for some Realtek chip workarounds
+ if( txlen < 60 ) //some strange limitation
+ txlen = 60;
+ else if( !(txlen % 64) ) //to handle module 64 packets
+ ++txlen;
+ }
+ txbuf = KMALLOC(txlen, 0);
+ memcpy( txbuf, buf, txlen );
+ }
+ ur = usb_make_request(softc->dev, softc->bulk_outpipe,
+ txbuf, txlen, UR_FLAG_OUT);
+ usb_sync_request(ur);
+ usb_free_request(ur);
+ KFREE(txbuf);
+
+ return( len );
+}
+
+
+/* *********************************************************************
+ * CFE-USB interfaces
+ ********************************************************************* */
+
+/* *********************************************************************
+ * usbeth_attach(dev,drv)
+ *
+ * This routine is called when the bus scan stuff finds a usb-ethernet
+ * device. We finish up the initialization by configuring the
+ * device and allocating our softc here.
+ *
+ * Input parameters:
+ * dev - usb device, in the "addressed" state.
+ * drv - the driver table entry that matched
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+const cfe_driver_t usbethdrv; //forward declaration
+
+static int usbeth_attach(usbdev_t *dev,usb_driver_t *drv)
+{
+ usb_config_descr_t *cfgdscr = dev->ud_cfgdescr;
+ usb_endpoint_descr_t *epdscr;
+ usb_endpoint_descr_t *indscr = NULL;
+ usb_endpoint_descr_t *outdscr = NULL;
+ usb_interface_descr_t *ifdscr;
+ usbeth_softc_t *softc;
+ int idx;
+
+ dev->ud_drv = drv;
+
+ softc = (usbeth_softc_t *) KMALLOC( sizeof(usbeth_softc_t), 0 );
+ if( softc == NULL )
+ {
+ xprintf( "Failed to allocate softc memory.\n" );
+ return -1;
+ }
+ memset( softc, 0, sizeof(usbeth_softc_t) );
+ dev->ud_private = softc;
+ softc->dev = dev;
+
+ ifdscr = usb_find_cfg_descr(dev,USB_INTERFACE_DESCRIPTOR_TYPE,0);
+ if (ifdscr == NULL)
+ {
+ xprintf("USBETH: ERROR...no interace descriptor\n");
+ return -1;
+ }
+
+
+ for (idx = 0; idx < 2; idx++)
+ {
+ epdscr = usb_find_cfg_descr(dev,USB_ENDPOINT_DESCRIPTOR_TYPE,idx);
+ if (USB_ENDPOINT_DIR_OUT(epdscr->bEndpointAddress))
+ outdscr = epdscr;
+ else
+ indscr = epdscr;
+ }
+
+ if (!indscr || !outdscr)
+ {
+ /*
+ * Could not get descriptors, something is very wrong.
+ * Leave device addressed but not configured.
+ */
+ xprintf("USBETH: ERROR...no endpoint descriptors\n");
+ return -1;
+ }
+
+ /*
+ * Choose the standard configuration.
+ */
+
+ usb_set_configuration(dev,cfgdscr->bConfigurationValue);
+
+ // Quit if not able to initialize the device
+ if (usbeth_init_device(softc) < 0)
+ return -1;
+
+ /*
+ * Open the pipes.
+ */
+
+ softc->bulk_inpipe = usb_open_pipe(dev,indscr);
+ softc->bulk_outpipe = usb_open_pipe(dev,outdscr);
+
+ //Now attach this device as a CFE Ethernet device
+ cfe_attach( (cfe_driver_t *) &usbethdrv, softc, NULL,
+ usbethdrv.drv_description );
+
+ ++Dev_cnt;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * usbeth_detach(dev)
+ *
+ * This routine is called when the bus scanner notices that
+ * this device has been removed from the system. We should
+ * do any cleanup that is required. The pending requests
+ * will be cancelled automagically.
+ *
+ * Input parameters:
+ * dev - usb device
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int usbeth_detach(usbdev_t *dev)
+{
+ usbeth_softc_t *softc = (usbeth_softc_t *) dev->ud_private;
+
+ --Dev_cnt;
+ KFREE(softc);
+
+ //*** SHOULD DETACH THE ETHERNET DEVICE TOO...LATER
+
+ return 0;
+}
+
+// CFE USB device interface structure
+usb_driver_t usbeth_driver =
+{
+ "Ethernet Device",
+ usbeth_attach,
+ usbeth_detach
+};
+
+
+
+/* *********************************************************************
+ * CFE-Ethernet device interfaces
+ ********************************************************************* */
+
+
+static int usbeth_ether_open(cfe_devctx_t *ctx)
+{
+ if( !Dev_cnt )
+ return CFE_ERR_NOTREADY;
+
+ USBETH_TRACE( "%s called.\n", __FUNCTION__ );
+ usbeth_open_device( (usbeth_softc_t *) ctx->dev_softc );
+
+ return 0;
+}
+
+static int usbeth_ether_read( cfe_devctx_t * ctx, iocb_buffer_t * buffer )
+{
+ if( !Dev_cnt )
+ return CFE_ERR_NOTREADY;
+
+ buffer->buf_retlen = usbeth_get_eth_frame( (usbeth_softc_t *)ctx->dev_softc,
+ buffer->buf_ptr );
+
+#ifdef DATA_DUMP
+ xprintf( "Incoming packet :\n" );
+ hexdump( buffer->buf_ptr, buffer->buf_retlen, 16,
+ buffer->buf_retlen / 16 + 1 );
+#endif
+
+ return 0;
+}
+
+
+static int usbeth_ether_inpstat( cfe_devctx_t * ctx, iocb_inpstat_t * inpstat )
+{
+ if( !Dev_cnt )
+ return CFE_ERR_NOTREADY;
+
+ inpstat->inp_status = usbeth_data_rx( (usbeth_softc_t *) ctx->dev_softc );
+
+ return 0;
+}
+
+
+static int usbeth_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ if( !Dev_cnt )
+ return CFE_ERR_NOTREADY;
+
+ // Block until hw notifies you data is sent.
+ usbeth_send_eth_frame( (usbeth_softc_t *) ctx->dev_softc, buffer->buf_ptr,
+ buffer->buf_length );
+
+ return 0;
+}
+
+
+static int usbeth_ether_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ int retval = 0;
+
+ if( !Dev_cnt )
+ return CFE_ERR_NOTREADY;
+
+ switch( (int)buffer->buf_ioctlcmd ) {
+ case IOCTL_ETHER_GETHWADDR:
+ USBETH_TRACE( "IOCTL_ETHER_GETHWADDR called.\n" );
+ usbeth_get_dev_addr( (usbeth_softc_t *) ctx->dev_softc,
+ buffer->buf_ptr );
+ break;
+ case IOCTL_ETHER_SETHWADDR:
+ xprintf( "IOCTL_ETHER_SETHWADDR not implemented.\n" );
+ break;
+#if 0
+ case IOCTL_ETHER_GETSPEED:
+ xprintf( "GETSPEED not implemented.\n" );
+ retval = -1;
+ break;
+ case IOCTL_ETHER_SETSPEED:
+ xprintf( "SETSPEED not implemented.\n" );
+ retval = -1;
+ break;
+ case IOCTL_ETHER_GETLINK:
+ xprintf( "GETLINK not implemented.\n" );
+ retval = -1;
+ break;
+ case IOCTL_ETHER_GETLOOPBACK:
+ xprintf( "GETLOOPBACK not implemented.\n" );
+ retval = -1;
+ break;
+ case IOCTL_ETHER_SETLOOPBACK:
+ xprintf( "SETLOOPBACK not implemented.\n" );
+ retval = -1;
+ break;
+#endif
+ default:
+ xprintf( "Invalid IOCTL to usbeth_ether_ioctl.\n" );
+ retval = -1;
+ }
+
+ return retval;
+}
+
+
+static int usbeth_ether_close(cfe_devctx_t *ctx)
+{
+ if( !Dev_cnt )
+ return CFE_ERR_NOTREADY;
+
+ USBETH_TRACE( "%s called.\n", __FUNCTION__ );
+ usbeth_close_device( (usbeth_softc_t *) ctx->dev_softc );
+
+ return 0;
+}
+
+
+// CFE ethernet device interface structures
+const static cfe_devdisp_t usbeth_ether_dispatch =
+{
+ usbeth_ether_open,
+ usbeth_ether_read,
+ usbeth_ether_inpstat,
+ usbeth_ether_write,
+ usbeth_ether_ioctl,
+ usbeth_ether_close,
+ NULL,
+ NULL
+};
+
+const cfe_driver_t usbethdrv =
+{
+ "USB-Ethernet Device",
+ "eth",
+ CFE_DEV_NETWORK,
+ &usbeth_ether_dispatch,
+ NULL, //probe...not needed
+};
+
diff --git a/cfe/cfe/usb/usbeth.h b/cfe/cfe/usb/usbeth.h
new file mode 100644
index 0000000..54f32ae
--- /dev/null
+++ b/cfe/cfe/usb/usbeth.h
@@ -0,0 +1,112 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * USB Ethernet File: usbeth.h
+ *
+ * Driver for USB Ethernet devices.
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+/* *********************************************************************
+ * USB-Ethernet adapter driver includes
+ ********************************************************************* */
+
+#ifndef __usbeth_h__
+#define __usbeth_h__
+
+/* **************************************
+ * CATC Netmate adapter
+ ************************************** */
+
+#define CATC_MCAST_TBL_ADDR 0xFA80 //in Netmate's SRAM
+#define CATC_GET_MAC_ADDR 0xF2
+#define CATC_SET_REG 0xFA
+#define CATC_GET_REG 0xFB
+#define CATC_SET_MEM 0xFC
+
+#define CATC_TX_BUF_CNT_REG 0x20
+#define CATC_RX_BUF_CNT_REG 0x21
+#define CATC_ADV_OP_MODES_REG 0x22
+#define CATC_RX_FRAME_CNT_REG 0x24
+
+#define CATC_ETH_CTRL_REG 0x60
+#define CATC_ENET_STATUS_REG 0x61
+#define CATC_ETH_ADDR_0_REG 0x67 // Byte #0 (leftmost)
+#define CATC_LED_CTRL_REG 0x81
+
+
+/* **************************************
+ * Admtek (PEGASUS II) adapter
+ ************************************** */
+
+#define PEG_SET_REG 0xF1
+#define PEG_GET_REG 0xF0
+
+#define PEG_MCAST_TBL_REG 0x08
+#define PEG_MAC_ADDR_0_REG 0x10
+#define PEG_EEPROM_OFS_REG 0x20
+#define PEG_EEPROM_DATA_REG 0x21
+#define PEG_EEPROM_CTL_REG 0x23
+#define PEG_PHY_ADDR_REG 0x25
+#define PEG_PHY_DATA_REG 0x26 //& 27 for 2 bytes
+#define PEG_PHY_CTRL_REG 0x28
+#define PEG_ETH_CTL0_REG 0x00
+#define PEG_ETH_CTL1_REG 0x01
+#define PEG_ETH_CTL2_REG 0x02
+#define PEG_GPIO0_REG 0x7e
+#define PEG_GPIO1_REG 0x7f
+#define PEG_INT_PHY_REG 0x7b
+
+#define PHY_WRITE 0x20
+#define PHY_READ 0x40
+
+
+/* **************************************
+ * Realtek adapter
+ ************************************** */
+
+#define RTEK_REG_ACCESS 0x05
+#define RTEK_MAC_REG 0x0120
+#define RTEK_CMD_REG 0x012E
+#define RTEK_RXCFG_REG 0x0130
+#define RTEK_RESET 0x10
+#define RTEK_AUTOLOAD 0x01
+
+
+
+#endif //__usbeth_h_
diff --git a/cfe/cfe/usb/usbhack.c b/cfe/cfe/usb/usbhack.c
new file mode 100644
index 0000000..647f213
--- /dev/null
+++ b/cfe/cfe/usb/usbhack.c
@@ -0,0 +1,528 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Main Module File: usbhack.c
+ *
+ * A crude test program to let us tinker with a USB controller
+ * installed in an X86 Linux PC. Eventually we'll clean up
+ * this stuff and incorporate it into CFE.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <sys/mman.h>
+#include <sys/fcntl.h>
+#include <signal.h>
+#include <memory.h>
+#include <time.h>
+
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "usbchap9.h"
+#include "usbd.h"
+#include "ohci.h"
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define OHCI_WRITECSR(softc,x,y) \
+ *((volatile uint32_t *) ((softc)->ohci_regs + ((x)/sizeof(uint32_t)))) = (y)
+#define OHCI_READCSR(softc,x) \
+ *((volatile uint32_t *) ((softc)->ohci_regs + ((x)/sizeof(uint32_t))))
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+extern int usb_noisy;
+extern int ohcidebug;
+
+extern usbdev_t *usbmass_dev;
+extern int usbmass_read_sector(usbdev_t *dev,uint32_t sectornum,uint32_t seccnt,
+ uint8_t *buffer);
+
+
+/* *********************************************************************
+ * Play Area definitions
+ *
+ * We use /dev/mem to map two areas - the "play" area and the
+ * "device" area.
+ *
+ * The "play" area maps to the upper 1MB of physical memory.
+ * You need to calculate this address yourself based on your system
+ * setup. If you have 256MB of memory, in your lilo.conf file put
+ * the following line:
+ *
+ * append="mem=255M"
+ *
+ * where '255' is one less than your system memory size. this
+ * leaves 1MB out of Linux's physical memory map and therefore
+ * leaves it to you to play with. /dev/mem will map this
+ * uncached using the Pentium MTRR registers, but for playing
+ * around this will be fine.
+ *
+ * the second area is the "device area" - this is the address
+ * the PCI USB controller's BARs were mapped to. You can find
+ * this by looking through /proc/pci until you find:
+ *
+ * Bus 0, device 8, function 0:
+ * USB Controller: OPTi Unknown device (rev 16).
+ * Vendor id=1045. Device id=c861.
+ * Medium devsel. Fast back-to-back capable. IRQ 3.
+ * Master Capable. Latency=32.
+ * Non-prefetchable 32 bit memory at 0xd9100000 [0xd9100000].
+ *
+ * The 0xd9100000 will probably be different on your system.
+ *
+ * Of course, to make this work you'll need to rebuild the kernel
+ * without USB support, if you're running a recent kernel.
+ * Fortunately(?), I've been using RH 6.2, no USB support there
+ * in the old 2.2 kernels.
+ *
+ * Finally, you'll need to run this program as root. Even if
+ * you mess with the permissions on /dev/mem, there are additional
+ * checks in the kernel, so you will lose.
+ *
+ * But, the good news is that it works well - I've never crashed
+ * my Linux box, and I can use gdb to debug programs.
+ * You will NOT be able to use GDB to display things in the
+ * play area - I believe GDB doesn't know how to deal with
+ * the uncached nature of the memory there. You can see stuff
+ * in the area by tracing through instructions that read the play
+ * area, and viewing the register contents.
+ ********************************************************************* */
+
+#define PLAY_AREA_ADDR (255*1024*1024) /* EDIT ME */
+#define PLAY_AREA_SIZE (1024*1024)
+int play_fd = -1;
+uint8_t *play_area = MAP_FAILED;
+
+#define DEVICE_AREA_ADDR 0xd9100000 /* EDIT ME */
+#define DEVICE_AREA_SIZE 4096
+int dev_fd = -1;
+uint8_t *device_area = MAP_FAILED;
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+
+usbbus_t *bus = NULL;
+ohci_softc_t *ohci = NULL;
+int running = 1;
+
+/* *********************************************************************
+ * vtop(v)
+ *
+ * Given a virtual address in the play area, return its physical
+ * address.
+ *
+ * Input parameters:
+ * v - virtual address
+ *
+ * Return value:
+ * physical address
+ ********************************************************************* */
+
+
+uint32_t vtop(void *v)
+{
+ uint32_t p = (uint32_t) v;
+
+ if (v == 0) return 0;
+
+ p -= (uint32_t) play_area;
+ p += PLAY_AREA_ADDR;
+
+ return p;
+}
+
+/* *********************************************************************
+ * ptov(v)
+ *
+ * Given a phyiscal address in the play area, return the virtual
+ * address.
+ *
+ * Input parameters:
+ * p - physical address
+ *
+ *
+ * Return value:
+ * virtual address (void pointer)
+ ********************************************************************* */
+
+void *ptov(uint32_t p)
+{
+ if (p == 0) return 0;
+
+ p -= PLAY_AREA_ADDR;
+ p += (uint32_t) play_area;
+
+ return (void *) p;
+}
+
+/* *********************************************************************
+ * mydelay(x)
+ *
+ * delay for 'x' milliseconds.
+ *
+ * Input parameters:
+ * x - milliseconds
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void mydelay(int x)
+{
+ struct timespec ts;
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = x * 1000000; /* milliseconds */
+ nanosleep(&ts,NULL);
+}
+
+/* *********************************************************************
+ * console_log(tmplt,...)
+ *
+ * Display a console log message - this is a CFE function
+ * transplanted here.
+ *
+ * Input parameters:
+ * tmplt - printf string args...
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void console_log(const char *tmplt,...)
+{
+ char buffer[256];
+ va_list marker;
+
+ va_start(marker,tmplt);
+ vsprintf(buffer,tmplt,marker);
+ va_end(marker);
+ printf("%s\n",buffer);
+}
+
+/* *********************************************************************
+ * init_devaccess()
+ *
+ * Open /dev/mem and create the play area
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0 if ok, else error
+ ********************************************************************* */
+
+int init_devaccess(void)
+{
+ int idx;
+
+ play_fd = open("/dev/mem",O_RDWR);
+
+ if (play_fd < 0) {
+ perror("open");
+ return -1;
+ }
+
+ dev_fd = open("/dev/mem",O_RDWR | O_SYNC);
+
+ if (dev_fd < 0) {
+ perror("open");
+ close(play_fd);
+ play_fd = -1;
+ return -1;
+ }
+
+ play_area = mmap(NULL,
+ PLAY_AREA_SIZE,
+ PROT_READ|PROT_WRITE,MAP_SHARED,
+ play_fd,
+ PLAY_AREA_ADDR);
+
+ if (play_area != MAP_FAILED) {
+ printf("Play area mapped ok at address %p to %p\n",play_area,play_area+PLAY_AREA_SIZE-1);
+ for (idx = 0; idx < PLAY_AREA_SIZE; idx++) {
+ play_area[idx] = 0x55;
+ if (play_area[idx] != 0x55) printf("Offset %x doesn't work\n",idx);
+ play_area[idx] = 0xaa;
+ if (play_area[idx] != 0xaa) printf("Offset %x doesn't work\n",idx);
+ play_area[idx] = 0x0;
+ if (play_area[idx] != 0x0) printf("Offset %x doesn't work\n",idx);
+ }
+ }
+ else {
+ perror("mmap");
+ close(play_fd);
+ close(dev_fd);
+ play_fd = -1;
+ dev_fd = -1;
+ return -1;
+ }
+
+ device_area = mmap(NULL,
+ DEVICE_AREA_SIZE,
+ PROT_READ|PROT_WRITE,MAP_SHARED,
+ dev_fd,
+ DEVICE_AREA_ADDR);
+
+ if (device_area != MAP_FAILED) {
+ printf("Device area mapped ok at address %p\n",device_area);
+ }
+ else {
+ perror("mmap");
+ munmap(play_area,PLAY_AREA_SIZE);
+ play_area = MAP_FAILED;
+ close(play_fd);
+ close(dev_fd);
+ play_fd = -1;
+ dev_fd = -1;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * uninit_devaccess()
+ *
+ * Turn off access to the /dev/mem area. this will also
+ * set the OHCI controller's state to reset if we were playing
+ * with it.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void uninit_devaccess(void)
+{
+ if (ohci->ohci_regs) {
+ OHCI_WRITECSR(ohci,R_OHCI_CONTROL,V_OHCI_CONTROL_HCFS(K_OHCI_HCFS_RESET));
+ }
+
+ if (play_area != MAP_FAILED) munmap(play_area,PLAY_AREA_SIZE);
+ if (device_area != MAP_FAILED) munmap(device_area,DEVICE_AREA_SIZE);
+
+ if (play_fd > 0) close(play_fd);
+ if (dev_fd > 0) close(dev_fd);
+
+ device_area = MAP_FAILED;
+ play_area = MAP_FAILED;
+
+ dev_fd = -1;
+ play_fd = -1;
+}
+
+/* *********************************************************************
+ * sighandler()
+ *
+ * ^C handler - switch off OHCI controller
+ *
+ * Input parameters:
+ * sig - signal
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void sighandler(int sig)
+{
+ signal(SIGINT,SIG_DFL);
+ printf("Interrupted, controller reset\n");
+ if (ohci->ohci_regs) {
+ OHCI_WRITECSR(ohci,R_OHCI_CONTROL,V_OHCI_CONTROL_HCFS(K_OHCI_HCFS_RESET));
+ }
+ running = 0;
+}
+
+
+extern usb_hcdrv_t ohci_driver;
+
+/* *********************************************************************
+ * xprintf(str)
+ *
+ * Called by lib_malloc, we need to supply it.
+ *
+ * Input parameters:
+ * str - string
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+int xprintf(char *str)
+{
+ printf("%s",str);
+ return 0;
+}
+
+/* *********************************************************************
+ * main(argc,argv)
+ *
+ * Main test program
+ *
+ * Input parameters:
+ * argc,argv - guess.
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+int main(int argc,char *argv[])
+{
+ int res;
+ memstats_t stats;
+ uint8_t *buffer;
+
+ /*
+ * Parse command line args
+ */
+
+ for (res = 1; res < argc; res++) {
+ if (strcmp(argv[res],"-o") == 0) ohcidebug++;
+ if (strcmp(argv[res],"-u") == 0) usb_noisy++;
+ }
+
+ /*
+ * Open the play area.
+ */
+
+ if (init_devaccess() < 0) {
+ printf("Could not map USB controller\n");
+ }
+
+ /*
+ * Establish signal and exit handlers
+ */
+
+ signal(SIGINT,sighandler);
+ atexit(uninit_devaccess);
+
+ /*
+ * Initialize a buffer pool to point at the play area.
+ * the 'malloc' calls inside our driver will therefore
+ * allocate memory suitable for DMA, just like on real
+ * hardware.
+ */
+
+ KMEMINIT(play_area,PLAY_AREA_SIZE);
+
+ buffer = KMALLOC(512,32);
+
+ printf("-------------------------------------------\n\n");
+
+ /*
+ * Create the OHCI driver instance.
+ */
+
+
+ bus = UBCREATE(&ohci_driver,(void *) device_area);
+
+ /*
+ * Hack: retrieve copy of softc for our exception handler
+ */
+
+ ohci = (ohci_softc_t *) bus->ub_hwsoftc;
+
+ /*
+ * Start the controller.
+ */
+
+ res = UBSTART(bus);
+
+ if (res != 0) {
+ printf("Could not init hardware\n");
+ UBSTOP(bus);
+ exit(1);
+ }
+
+ /*
+ * Init the root hub
+ */
+
+ usb_initroot(bus);
+
+ /*
+ * Main loop - just call interrupt routine to poll
+ */
+
+ while (usbmass_dev== NULL) {
+ usb_poll(bus);
+ usb_daemon(bus);
+ }
+
+ for (res = 0; res < 1000; res++) {
+ usbmass_read_sector(usbmass_dev,0,1,buffer);
+ }
+
+ printf("----- finished reading all sectors ----\n");
+
+ while (running) {
+ usb_poll(bus);
+ usb_daemon(bus);
+ }
+
+ /*
+ * Clean up - get heap statistics to see if we
+ * screwed up.
+ */
+
+ res = KMEMSTATS(&stats);
+ if (res < 0) printf("Warning: heap is not consistent\n");
+ else printf("Heap is ok\n");
+
+ exit(0);
+
+}
diff --git a/cfe/cfe/usb/usbhack.h b/cfe/cfe/usb/usbhack.h
new file mode 100644
index 0000000..9f95840
--- /dev/null
+++ b/cfe/cfe/usb/usbhack.h
@@ -0,0 +1,66 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * usb test harness definitions File: usbhack.h
+ *
+ * Anything special required by the test harness is defined
+ * here.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+void console_log(const char *tmplt,...);
+
diff --git a/cfe/cfe/usb/usbhack.mk b/cfe/cfe/usb/usbhack.mk
new file mode 100644
index 0000000..361973e
--- /dev/null
+++ b/cfe/cfe/usb/usbhack.mk
@@ -0,0 +1,23 @@
+
+OBJS = usbhack.o lib_malloc.o lib_queue.o ohci.o usbd.o \
+ usbdevs.o usbhub.o usbdebug.o usbhid.o usbmass.o usbserial.o
+
+CFLAGS = -I../include -g -Wall
+VPATH = ../lib
+
+%.o : %.c
+ gcc $(CFLAGS) -c -o $@ $<
+
+all : usbhack
+ echo done
+
+usbhack : $(OBJS)
+ gcc -o usbhack $(OBJS)
+
+lib_malloc.o : lib_malloc.c
+
+usbhack.o : usbhack.c
+
+
+clean :
+ rm -f *.o usbhack
diff --git a/cfe/cfe/usb/usbhid.c b/cfe/cfe/usb/usbhid.c
new file mode 100644
index 0000000..df84f4e
--- /dev/null
+++ b/cfe/cfe/usb/usbhid.c
@@ -0,0 +1,664 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * USB Human Interface Driver File: usbhid.c
+ *
+ * This module deals with keyboards, mice, etc. It's very simple,
+ * and only the "boot protocol" is supported.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#ifndef _CFE_
+#include <stdio.h>
+#include <time.h>
+#include <memory.h>
+#include <stdint.h>
+#include "usbhack.h"
+#else
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+#include "cfe_console.h"
+#endif
+
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "usbchap9.h"
+#include "usbd.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define HID_BOOT_PROTOCOL 0
+#define HID_REPORT_PROTOCOL 1
+
+#define HID_DEVTYPE_UNKNOWN 0
+#define HID_DEVTYPE_KBD 1
+#define HID_DEVTYPE_MOUSE 2
+#define HID_DEVTYPE_MAX 2
+
+#define UBR_KBD_MODS 0
+#define UBR_KBD_RSVD 1
+#define UBR_KBD_KEYS 2
+#define UBR_KBD_NUMKEYS 6
+#define UBR_KBD_MAX 8
+
+#define KBD_MOD_LCTRL 0x01
+#define KBD_MOD_LSHIFT 0x02
+#define KBD_MOD_LALT 0x04
+#define KBD_MOD_LWIN 0x08
+
+#define KBD_MOD_RCTRL 0x10
+#define KBD_MOD_RSHIFT 0x20
+#define KBD_MOD_RALT 0x40
+#define KBD_MOD_RWIN 0x80
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define usbhid_set_protocol(dev,protocol,ifc) \
+ usb_simple_request(dev,0x21,0x0B,0,ifc)
+
+
+/* *********************************************************************
+ * Forward Definitions
+ ********************************************************************* */
+
+static int usbhid_attach(usbdev_t *dev,usb_driver_t *drv);
+static int usbhid_detach(usbdev_t *dev);
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef struct usbhid_softc_s {
+ int uhid_ipipe;
+ int uhid_ipipemps;
+ int uhid_devtype;
+ uint8_t uhid_imsg[UBR_KBD_MAX];
+ uint8_t uhid_lastmsg[UBR_KBD_MAX];
+ uint32_t uhid_shiftflags;
+} usbhid_softc_t;
+
+usb_driver_t usbhid_driver = {
+ "Human-Interface Device",
+ usbhid_attach,
+ usbhid_detach
+};
+
+static char *usbhid_devtypes[3] = {
+ "Unknown",
+ "Keyboard",
+ "Mouse"};
+
+#ifdef CFG_VGACONSOLE
+extern int pcconsole_enqueue(uint8_t ch);
+#endif
+
+
+/* *********************************************************************
+ * Constants for keyboard table
+ ********************************************************************* */
+
+#define FLG_NUM 0x0001 /* Toggles: same as bits for LEDs */
+#define FLG_CAPS 0x0002
+#define FLG_SCROLL 0x0004
+#define FLG_SHIFT 0x0008 /* Shifts */
+#define FLG_CTRL 0x0100
+#define FLG_ALT 0x0200
+#define FLG_FKEY 0x0400 /* function keys */
+#define FLG_NKPD 0x0800 /* numeric keypad */
+#define FLG_ASCII 0x1000 /* regular ASCII character */
+#define FLG_NONE 0x2000
+
+
+/* *********************************************************************
+ * Structures for keyboard table
+ ********************************************************************* */
+
+#define KC_RESPLEN 4
+typedef struct keycode_s {
+ int kc_type;
+ char kc_normal[KC_RESPLEN];
+ char kc_shifted[KC_RESPLEN];
+ char kc_ctrl[KC_RESPLEN];
+} keycode_t;
+
+
+/* *********************************************************************
+ * Scan code conversion table
+ ********************************************************************* */
+
+static keycode_t usbhid_scantable[] = {
+ { FLG_NONE, "", "", "" }, /* 0 */
+ { FLG_NONE, "", "", "" }, /* 1 */
+ { FLG_NONE, "", "", "" }, /* 2 */
+ { FLG_NONE, "", "", "" }, /* 3 */
+ { FLG_ASCII, "a", "A", "\001" }, /* 4 a */
+ { FLG_ASCII, "b", "B", "\002" }, /* 5 b */
+ { FLG_ASCII, "c", "C", "\003" }, /* 6 c */
+ { FLG_ASCII, "d", "D", "\004" }, /* 7 d */
+ { FLG_ASCII, "e", "E", "\005" }, /* 8 e */
+ { FLG_ASCII, "f", "F", "\006" }, /* 9 f */
+ { FLG_ASCII, "g", "G", "\007" }, /* 10 g */
+ { FLG_ASCII, "h", "H", "\010" }, /* 11 h */
+ { FLG_ASCII, "i", "I", "\011" }, /* 12 i */
+ { FLG_ASCII, "j", "J", "\n" }, /* 13 j */
+ { FLG_ASCII, "k", "K", "\013" }, /* 14 k */
+ { FLG_ASCII, "l", "L", "\014" }, /* 15 l */
+ { FLG_ASCII, "m", "M", "\r" }, /* 16 m */
+ { FLG_ASCII, "n", "N", "\016" }, /* 17 n */
+ { FLG_ASCII, "o", "O", "\017" }, /* 18 o */
+ { FLG_ASCII, "p", "P", "\020" }, /* 19 p */
+ { FLG_ASCII, "q", "Q", "\021" }, /* 20 q */
+ { FLG_ASCII, "r", "R", "\022" }, /* 21 r */
+ { FLG_ASCII, "s", "S", "\023" }, /* 22 s */
+ { FLG_ASCII, "t", "T", "\024" }, /* 23 t */
+ { FLG_ASCII, "u", "U", "\025" }, /* 24 u */
+ { FLG_ASCII, "v", "V", "\026" }, /* 25 v */
+ { FLG_ASCII, "w", "W", "\027" }, /* 26 w */
+ { FLG_ASCII, "x", "X", "\030" }, /* 27 x */
+ { FLG_ASCII, "y", "Y", "\031" }, /* 28 y */
+ { FLG_ASCII, "z", "Z", "\032" }, /* 29 z */
+
+ { FLG_ASCII, "1", "!", "!" }, /* 30 1 */
+ { FLG_ASCII, "2", "@", "\000" }, /* 31 2 */
+ { FLG_ASCII, "3", "#", "#" }, /* 32 3 */
+ { FLG_ASCII, "4", "$", "$" }, /* 33 4 */
+ { FLG_ASCII, "5", "%", "%" }, /* 34 5 */
+ { FLG_ASCII, "6", "^", "\036" }, /* 35 6 */
+ { FLG_ASCII, "7", "&", "&" }, /* 36 7 */
+ { FLG_ASCII, "8", "*", "\010" }, /* 37 8 */
+ { FLG_ASCII, "9", "(", "(" }, /* 38 9 */
+ { FLG_ASCII, "0", ")", ")" }, /* 39 0 */
+
+ { FLG_ASCII, "\r", "\r", "\n" }, /* 40 ENT */
+ { FLG_ASCII, "\033", "\033", "\033" }, /* 41 ESC */
+ { FLG_ASCII, "\177", "\177", "\010" }, /* 42 <- */
+ { FLG_ASCII, "\t", "\177\t", "\t" }, /* 43 ->| */
+ { FLG_ASCII, " ", " ", "\000" }, /* 44 SPC */
+
+ { FLG_ASCII, "-", "_", "\037" }, /* 45 - */
+ { FLG_ASCII, "=", "+", "+" }, /* 46 = */
+ { FLG_ASCII, "[", "{", "\033" }, /* 47 [ */
+ { FLG_ASCII, "]", "}", "\035" }, /* 48 ] */
+ { FLG_ASCII, "\\", "|", "\034" }, /* 49 \ */
+
+ { FLG_NONE, "", "", "" }, /* 50 pound */
+
+ { FLG_ASCII, ";", ":", ";" }, /* 51 ; */
+ { FLG_ASCII, "'", "\"", "'" }, /* 52 ' */
+ { FLG_ASCII, "`", "~", "`" }, /* 53 ` */
+ { FLG_ASCII, ",", "<", "<" }, /* 54 , */
+ { FLG_ASCII, ".", ">", ">" }, /* 55 . */
+ { FLG_ASCII, "/", "?", "\037" }, /* 56 / */
+ { FLG_CAPS, "", "", "" }, /* 57 CAPS */
+
+ { FLG_FKEY, "\033[M", "\033[Y", "\033[k" }, /* 58 f1 */
+ { FLG_FKEY, "\033[N", "\033[Z", "\033[l" }, /* 59 f2 */
+ { FLG_FKEY, "\033[O", "\033[a", "\033[m" }, /* 60 f3 */
+ { FLG_FKEY, "\033[P", "\033[b", "\033[n" }, /* 61 f4 */
+ { FLG_FKEY, "\033[Q", "\033[c", "\033[o" }, /* 62 f5 */
+ { FLG_FKEY, "\033[R", "\033[d", "\033[p" }, /* 63 f6 */
+ { FLG_FKEY, "\033[S", "\033[e", "\033[q" }, /* 64 f7 */
+ { FLG_FKEY, "\033[T", "\033[f", "\033[r" }, /* 65 f8 */
+ { FLG_FKEY, "\033[U", "\033[g", "\033[s" }, /* 66 f9 */
+ { FLG_FKEY, "\033[V", "\033[h", "\033[t" }, /* 67 f10 */
+ { FLG_FKEY, "\033[W", "\033[i", "\033[u" }, /* 68 f11 */
+ { FLG_FKEY, "\033[X", "\033[j", "\033[v" }, /* 69 f12 */
+
+ { FLG_NONE, "", "", "" }, /* 70 prtsc */
+ { FLG_SCROLL, "", "", "" }, /* 71 SCRLK */
+ { FLG_NONE, "", "", "" }, /* 72 pause */
+ { FLG_NONE, "", "", "" }, /* 73 KPins */
+ { FLG_NONE, "", "", "" }, /* 74 KPhome */
+ { FLG_NONE, "", "", "" }, /* 75 KPpgup */
+ { FLG_NONE, "", "", "" }, /* 76 KPdel */
+ { FLG_NONE, "", "", "" }, /* 77 KPend */
+ { FLG_NONE, "", "", "" }, /* 78 KPpgdn */
+
+ { FLG_FKEY, "\033[C", "", "" }, /* 79 KPright */
+ { FLG_FKEY, "\033[D", "", "" }, /* 80 KPleft */
+ { FLG_FKEY, "\033[B", "", "" }, /* 81 KPdown */
+ { FLG_FKEY, "\033[A", "", "" }, /* 82 KPup */
+
+ { FLG_NUM, "", "", "" }, /* 83 NUMLK */
+ { FLG_NKPD, "/", "/", "/" }, /* 84 KP/ */
+ { FLG_NKPD, "*", "*", "*" }, /* 85 KP* */
+ { FLG_NKPD, "-", "-", "-" }, /* 86 KP- */
+ { FLG_NKPD, "+", "+", "+" }, /* 87 KP+ */
+ { FLG_NKPD, "\r", "\r", "\n" }, /* 88 KPent */
+
+ { FLG_NKPD, "1", "\033[F", "1" }, /* 89 KP1 */
+ { FLG_NKPD, "2", "\033[B", "2" }, /* 90 KP2 */
+ { FLG_NKPD, "3", "\033[G", "3" }, /* 91 KP3 */
+ { FLG_NKPD, "4", "\033[D", "4" }, /* 92 KP4 */
+ { FLG_NKPD, "5", "\033[E", "5" }, /* 93 KP5 */
+ { FLG_NKPD, "6", "\033[C", "6" }, /* 94 KP6 */
+ { FLG_NKPD, "7", "\033[H", "7" }, /* 95 KP7 */
+ { FLG_NKPD, "8", "\033[A", "8" }, /* 96 KP8 */
+ { FLG_NKPD, "9", "\033[I", "9" }, /* 97 KP9 */
+ { FLG_NKPD, "0", "\033[L", "0" }, /* 98 KP0 */
+
+ { FLG_NKPD, ".", "\177", "." }, /* 99 KP. */
+
+ { FLG_NONE, "", "", "" }, /* 100 non\ */
+
+};
+
+#define usbhid_scantablesize (sizeof(usbhid_scantable)/sizeof(keycode_t))
+
+
+/* *********************************************************************
+ * usbhid_kbd_mod1(uhid)
+ *
+ * Process modifier key changes for the current USB event,
+ * which was stored in uhid_imsg. Basically all this does
+ * is update uhid_shiftflags, converting the bits into the ones
+ * we use in our keyboard table.
+ *
+ * Input parameters:
+ * uhid - the hid softc.
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void usbhid_kbd_mod1(usbhid_softc_t *uhid)
+{
+ uint8_t changed;
+ uint8_t mod;
+
+ /*
+ * See if anything changed.
+ */
+
+ changed = (uhid->uhid_imsg[UBR_KBD_MODS] ^ uhid->uhid_lastmsg[UBR_KBD_MODS]);
+ if (changed == 0) return;
+
+ /*
+ * Something changed. Reflect changes in our local copy of the
+ * shift state.
+ */
+
+ mod = uhid->uhid_imsg[UBR_KBD_MODS];
+
+ uhid->uhid_shiftflags &= ~(FLG_SHIFT|FLG_ALT|FLG_CTRL);
+
+ if (mod & (KBD_MOD_LCTRL|KBD_MOD_RCTRL)) uhid->uhid_shiftflags |= FLG_CTRL;
+ if (mod & (KBD_MOD_LSHIFT|KBD_MOD_RSHIFT)) uhid->uhid_shiftflags |= FLG_SHIFT;
+ if (mod & (KBD_MOD_LALT|KBD_MOD_RALT)) uhid->uhid_shiftflags |= FLG_ALT;
+}
+
+/* *********************************************************************
+ * usbhid_kbd_scan1(uhid,scan,breakflg)
+ *
+ * Handle a single keyboard event. Using the scan code, look up
+ * the key in the table and convert it to one or more characters
+ * for the keyboard event queue.
+ *
+ * Input parameters:
+ * uhid - the hid softc
+ * scan - scan code from keyboard report
+ * breakflg - true if key is being released, false if pressed
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void usbhid_kbd_scan1(usbhid_softc_t *uhid,uint8_t scan,int breakflg)
+{
+ keycode_t *code = 0;
+ char *str;
+
+ /*
+ * Check scan code for reality.
+ */
+
+ if (scan >= usbhid_scantablesize) return;
+ code = &usbhid_scantable[scan];
+
+ /*
+ * If the change is a toggle, handle the toggle. These
+ * keys also deal with the LEDs on the keyboard.
+ */
+
+ if (code->kc_type & (FLG_CAPS|FLG_SCROLL|FLG_NUM)) {
+ if (!breakflg) uhid->uhid_shiftflags ^= code->kc_type;
+// if (ks->ks_setleds) {
+// (*(ks->ks_setleds))(ks,ks->ks_shiftflags & (FLG_CAPS|FLG_SCROLL|FLG_NUM));
+// }
+ }
+
+ /*
+ * Regular keys - just look up in table and
+ * queue the characters to the upper layers.
+ */
+
+ if (code->kc_type & (FLG_ASCII | FLG_FKEY | FLG_NKPD)) {
+ if (uhid->uhid_shiftflags & (FLG_SHIFT|FLG_CAPS)) str = code->kc_shifted;
+ else if (uhid->uhid_shiftflags & FLG_CTRL) str = code->kc_ctrl;
+ else str = code->kc_normal;
+ if (!breakflg) {
+#if CFG_VGACONSOLE
+ while (*str) {
+ pcconsole_enqueue(*str++);
+ }
+#else
+ printf("%s",str);
+#endif
+#ifndef _CFE_
+ fflush(stdout);
+#endif
+ }
+ }
+
+}
+
+
+/* *********************************************************************
+ * usbhid_kbd_scan(uhid)
+ *
+ * Main processing routine for keyboard report messages. Once
+ * we've determined that it is a keyboard mesage, we end up
+ * here. The work involves seeing what new keys have arrived
+ * in the list (presses), and which ones are no longer there
+ * (releases). To do this, we us the current and previous
+ * report structure.
+ *
+ * Input parameters:
+ * uhid - the hid softc
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void usbhid_kbd_scan(usbhid_softc_t *uhid)
+{
+ int n,o;
+
+ /*
+ * Modifier keys (shift, alt, control)
+ */
+
+ if (uhid->uhid_imsg[UBR_KBD_MODS] ^ uhid->uhid_lastmsg[UBR_KBD_MODS]) {
+ usbhid_kbd_mod1(uhid);
+ }
+
+ /*
+ * "Make" codes (keys pressed down)
+ * Look for keys in 'uhid_imsg' that are not in 'uhid_lastmsg'
+ */
+
+ for (n = UBR_KBD_KEYS; n < (UBR_KBD_KEYS + UBR_KBD_NUMKEYS); n++) {
+ if (uhid->uhid_imsg[n] == 0) break; /* no more keys */
+ for (o = UBR_KBD_KEYS; o < (UBR_KBD_KEYS + UBR_KBD_NUMKEYS); o++) {
+ if (uhid->uhid_imsg[n] == uhid->uhid_lastmsg[o]) break;
+ }
+ if (o == (UBR_KBD_KEYS + UBR_KBD_NUMKEYS)) { /* key not found, must be pressed */
+ usbhid_kbd_scan1(uhid,uhid->uhid_imsg[n],0);
+ }
+ }
+
+ /*
+ * "Break" codes (keys released)
+ * Look for keys in 'uhid_lastmsg' that are not in 'uhid_imsg'
+ */
+
+
+ for (n = UBR_KBD_KEYS; n < (UBR_KBD_KEYS + UBR_KBD_NUMKEYS); n++) {
+ if (uhid->uhid_lastmsg[n] == 0) break; /* no more keys */
+ for (o = UBR_KBD_KEYS; o < (UBR_KBD_KEYS + UBR_KBD_NUMKEYS); o++) {
+ if (uhid->uhid_lastmsg[n] == uhid->uhid_imsg[o]) break;
+ }
+ if (o == (UBR_KBD_KEYS + UBR_KBD_NUMKEYS)) { /* key not found, must be released */
+ usbhid_kbd_scan1(uhid,uhid->uhid_lastmsg[n],1);
+ }
+ }
+}
+
+
+/* *********************************************************************
+ * usbhid_ireq_callback(ur)
+ *
+ * This routine is called when our interrupt transfer completes
+ * and there is report data to be processed.
+ *
+ * Input parameters:
+ * ur - usb request
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int usbhid_ireq_callback(usbreq_t *ur)
+{
+ usbhid_softc_t *uhid = (ur->ur_dev->ud_private);
+
+ /*
+ * If the driver is unloaded, the request will be cancelled.
+ */
+
+ if (ur->ur_status == 0xFF) {
+ usb_free_request(ur);
+ return 0;
+ }
+
+ /*
+ * What we do now depends on the type of device.
+ */
+
+ switch (uhid->uhid_devtype) {
+ case HID_DEVTYPE_KBD:
+ /*
+ * Handle keyboard event
+ */
+ usbhid_kbd_scan(uhid);
+
+ /*
+ * Save old event to compare for next time.
+ */
+ memcpy(uhid->uhid_lastmsg,uhid->uhid_imsg,8);
+ break;
+
+ case HID_DEVTYPE_MOUSE:
+#if 0
+ /*
+ * No need to handle mice, but here's the good stuff.
+ */
+ printf("Mouse: [%s %s %s] X:%d Y:%d Wheel:%d\n",
+ (ur->ur_buffer[0] & 1) ? "left" : "",
+ (ur->ur_buffer[0] & 4) ? "middle" : "",
+ (ur->ur_buffer[0] & 2) ? "right" : "",
+ (int)(signed char)ur->ur_buffer[1],
+ (int)(signed char)ur->ur_buffer[2],
+ (int)(signed char)ur->ur_buffer[3]);
+#endif
+ break;
+ }
+
+ /*
+ * Re-queue request to get next keyboard event.
+ */
+
+ usb_queue_request(ur);
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * usbhid_queue_intreq(dev,softc)
+ *
+ * Queue an interrupt request for this usb device. The
+ * driver will place this request on the queue that corresponds
+ * to the endpoint, and will call the callback routine when
+ * something happens.
+ *
+ * Input parameters:
+ * dev - usb device
+ * softc - the usb hid softc
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void usbhid_queue_intreq(usbdev_t *dev,usbhid_softc_t *softc)
+{
+ usbreq_t *ur;
+
+ ur = usb_make_request(dev,
+ softc->uhid_ipipe,
+ softc->uhid_imsg,softc->uhid_ipipemps,
+ UR_FLAG_IN);
+
+ ur->ur_callback = usbhid_ireq_callback;
+
+ usb_queue_request(ur);
+}
+
+
+/* *********************************************************************
+ * usbhid_attach(dev,drv)
+ *
+ * This routine is called when the bus scan stuff finds a HID
+ * device. We finish up the initialization by configuring the
+ * device and allocating our softc here.
+ *
+ * Input parameters:
+ * dev - usb device, in the "addressed" state.
+ * drv - the driver table entry that matched
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int usbhid_attach(usbdev_t *dev,usb_driver_t *drv)
+{
+ usb_config_descr_t *cfgdscr = dev->ud_cfgdescr;
+ usb_endpoint_descr_t *epdscr;
+ usb_interface_descr_t *ifdscr;
+ usbhid_softc_t *softc;
+
+ dev->ud_drv = drv;
+
+ softc = KMALLOC(sizeof(usbhid_softc_t),0);
+ memset(softc,0,sizeof(usbhid_softc_t));
+ dev->ud_private = softc;
+
+ epdscr = usb_find_cfg_descr(dev,USB_ENDPOINT_DESCRIPTOR_TYPE,0);
+ ifdscr = usb_find_cfg_descr(dev,USB_INTERFACE_DESCRIPTOR_TYPE,0);
+
+ if (!epdscr || !ifdscr) {
+ /*
+ * Could not get descriptors, something is very wrong.
+ * Leave device addressed but not configured.
+ */
+ return 0;
+ }
+
+ /*
+ * Choose the standard configuration.
+ */
+
+ usb_set_configuration(dev,cfgdscr->bConfigurationValue);
+
+ /*
+ * Set the protocol to the "boot" protocol, so we don't
+ * have to deal with fancy HID stuff.
+ */
+
+ usbhid_set_protocol(dev,HID_BOOT_PROTOCOL,ifdscr->bInterfaceNumber);
+
+ /*
+ * Open the interrupt pipe.
+ */
+
+ softc->uhid_ipipe = usb_open_pipe(dev,epdscr);
+ softc->uhid_ipipemps = GETUSBFIELD(epdscr,wMaxPacketSize);
+
+ /*
+ * Figure out the device type from the protocol. Keyboards,
+ * mice use this field to distinguish themselves.
+ */
+
+ softc->uhid_devtype = ifdscr->bInterfaceProtocol;
+ if (softc->uhid_devtype > HID_DEVTYPE_MAX) {
+ softc->uhid_devtype = HID_DEVTYPE_UNKNOWN;
+ }
+
+ console_log("USBHID: %s Configured.\n",
+ usbhid_devtypes[softc->uhid_devtype]);
+
+ /*
+ * Queue a transfer on the interrupt endpoint to catch
+ * our first characters.
+ */
+
+ usbhid_queue_intreq(dev,softc);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * usbhid_detach(dev)
+ *
+ * This routine is called when the bus scanner notices that
+ * this device has been removed from the system. We should
+ * do any cleanup that is required. The pending requests
+ * will be cancelled automagically.
+ *
+ * Input parameters:
+ * dev - usb device
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int usbhid_detach(usbdev_t *dev)
+{
+ return 0;
+}
+
+
+
diff --git a/cfe/cfe/usb/usbhub.c b/cfe/cfe/usb/usbhub.c
new file mode 100644
index 0000000..1e571ed
--- /dev/null
+++ b/cfe/cfe/usb/usbhub.c
@@ -0,0 +1,912 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * USB Hub and device discovery code File: usbhub.c
+ *
+ * This module deals with hubs and device discovery.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#ifndef _CFE_
+#include <stdio.h>
+#include <time.h>
+#include <memory.h>
+#include <stdint.h>
+#include "usbhack.h"
+#else
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+#include "cfe_console.h"
+#endif
+
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "usbchap9.h"
+#include "usbd.h"
+
+/* *********************************************************************
+ * Macros for common hub requests
+ ********************************************************************* */
+
+#define usbhub_set_port_feature(dev,port,feature) \
+ usb_simple_request(dev,0x23,USB_HUBREQ_SET_FEATURE,feature,port)
+
+#define usbhub_set_hub_feature(dev,feature) \
+ usb_simple_request(dev,0x20,USB_HUBREQ_SET_FEATURE,feature,0)
+
+#define usbhub_clear_port_feature(dev,port,feature) \
+ usb_simple_request(dev,0x23,USB_HUBREQ_CLEAR_FEATURE,feature,port)
+
+#define usbhub_clear_hub_feature(dev,feature) \
+ usb_simple_request(dev,0x20,USB_HUBREQ_CLEAR_FEATURE,feature,0)
+
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+extern int usb_noisy;
+
+/* *********************************************************************
+ * Forward declarations
+ ********************************************************************* */
+
+static int usbhub_attach(usbdev_t *dev,usb_driver_t *drv);
+static int usbhub_detach(usbdev_t *dev);
+
+/* *********************************************************************
+ * Hub-specific data structures
+ ********************************************************************* */
+
+#define UHUB_MAX_DEVICES 8
+
+#define UHUB_FLG_NEEDSCAN 1
+
+typedef struct usbhub_softc_s {
+ usb_hub_descr_t uhub_descr;
+ usb_hub_status_t uhub_status;
+ int uhub_ipipe;
+ int uhub_ipipemps;
+ int uhub_nports;
+ unsigned int uhub_flags;
+ uint8_t uhub_imsg[8];
+ usbdev_t *uhub_devices[UHUB_MAX_DEVICES];
+} usbhub_softc_t;
+
+usb_driver_t usbhub_driver = {
+ "USB Hub",
+ usbhub_attach,
+ usbhub_detach
+};
+
+
+/* *********************************************************************
+ * usbhub_ireq_callback(ur)
+ *
+ * this routine is called when the transfer we queued to the
+ * interrupt endpoint on the hub completes. It means that
+ * *some* port on the hub needs attention. The data indicates
+ * which port, but for our purposes we don't really care - if
+ * we get this callback, we'll set a flag and re-probe the bus.
+ *
+ * Input parameters:
+ * ur - usbreq that completed
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int usbhub_ireq_callback(usbreq_t *ur)
+{
+ int idx;
+ usbhub_softc_t *uhub = (ur->ur_dev->ud_private);
+
+ /*
+ * Check to see if the request was cancelled by someone
+ * deleting our endpoint.
+ */
+
+ if (ur->ur_status == 0xFF) {
+ usb_free_request(ur);
+ return 0;
+ }
+
+ /*
+ * Check to see if any of our ports need attention
+ */
+
+ for (idx = 1; idx <= uhub->uhub_nports; idx++) {
+ if (ur->ur_buffer[0] & (1<<idx)) {
+
+ /*
+ * Mark the hub as needing a scan, and mark the bus as well
+ * so the top-level polling will notice.
+ */
+
+ uhub->uhub_flags |= UHUB_FLG_NEEDSCAN;
+ ur->ur_dev->ud_bus->ub_flags |= UB_FLG_NEEDSCAN;
+ }
+ }
+
+
+ /*
+ * Do NOT requeue the request here. We will do this
+ * during exploration.
+ */
+
+ usb_free_request(ur);
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * usbhub_get_hub_descriptor(dev,dscr,idx,maxlen)
+ *
+ * Obtain the hub descriptor (special for hubs) from the
+ * device.
+ *
+ * Input parameters:
+ * dev - usb device
+ * dscr - place to put hub descriptor
+ * idx - which hub descriptor to get (usually zero)
+ * maxlen - max # of bytes to return
+ *
+ * Return value:
+ * # of bytes returned
+ ********************************************************************* */
+
+static int usbhub_get_hub_descriptor(usbdev_t *dev,usb_hub_descr_t *dscr,int idx,int maxlen)
+{
+ return usb_std_request(dev,0xA0,
+ USB_HUBREQ_GET_DESCRIPTOR,
+ 0,0,
+ (uint8_t *) dscr,
+ maxlen);
+}
+
+
+/* *********************************************************************
+ * usbhub_get_hub_status(dev,status)
+ *
+ * Obtain the hub status (special for hubs) from the
+ * device.
+ *
+ * Input parameters:
+ * dev - usb device
+ * status - where to put hub status structure
+ *
+ * Return value:
+ * # of bytes returned
+ ********************************************************************* */
+
+#if 0
+static int usbhub_get_hub_status(usbdev_t *dev,usb_hub_status_t *status)
+{
+ return usb_std_request(dev,
+ 0xA0,
+ 0x00,
+ 0,
+ 0,
+ (uint8_t *) status,
+ sizeof(usbhub_status_t));
+}
+#endif
+
+
+/* *********************************************************************
+ * usbhub_get_port_status(dev,port,status)
+ *
+ * Obtain the port status for a particular port from
+ * device.
+ *
+ * Input parameters:
+ * dev - usb device
+ * port - 1-based port number
+ * status - where to put port status structure
+ *
+ * Return value:
+ * # of bytes returned
+ ********************************************************************* */
+
+static int usbhub_get_port_status(usbdev_t *dev,int port,usb_port_status_t *status)
+{
+ return usb_std_request(dev,
+ 0xA3,
+ 0,
+ 0,
+ port,
+ (uint8_t *) status,
+ sizeof(usb_port_status_t));
+}
+
+
+/* *********************************************************************
+ * usbhub_queue_intreq(dev,softc)
+ *
+ * Queue the transfer to the interrupt pipe that will catch
+ * the hub's port status changes
+ *
+ * Input parameters:
+ * dev - usb device
+ * softc - hub-specific data
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void usbhub_queue_intreq(usbdev_t *dev,usbhub_softc_t *softc)
+{
+ usbreq_t *ur;
+
+ ur = usb_make_request(dev,
+ softc->uhub_ipipe,
+ softc->uhub_imsg,softc->uhub_ipipemps,
+ UR_FLAG_IN | UR_FLAG_SHORTOK);
+
+ ur->ur_callback = usbhub_ireq_callback;
+
+ usb_queue_request(ur);
+}
+
+
+/* *********************************************************************
+ * usbhub_attach(dev,drv)
+ *
+ * This routine is called when the hub attaches to the system.
+ * We complete initialization for the hub and set things up so
+ * that an explore will happen soon.
+ *
+ * Input parameters:
+ * dev - usb device
+ * drv - driver structure
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int usbhub_attach(usbdev_t *dev,usb_driver_t *drv)
+{
+ usb_device_status_t devstatus;
+ usb_config_descr_t *cfgdscr;
+ usb_interface_descr_t *ifdscr;
+ usb_endpoint_descr_t *epdscr;
+ usbhub_softc_t *softc;
+
+ /*
+ * Remember the driver dispatch.
+ */
+
+ dev->ud_drv = drv;
+
+ softc = KMALLOC(sizeof(usbhub_softc_t),0);
+ memset(softc,0,sizeof(usbhub_softc_t));
+ dev->ud_private = softc;
+
+ /*
+ * Dig out the data from the configuration descriptor
+ * (we got this from the device before attach time)
+ */
+
+ cfgdscr = dev->ud_cfgdescr;
+ epdscr = usb_find_cfg_descr(dev,USB_ENDPOINT_DESCRIPTOR_TYPE,0);
+ ifdscr = usb_find_cfg_descr(dev,USB_INTERFACE_DESCRIPTOR_TYPE,0);
+
+ /*
+ * Get device status (is this really necessary?)
+ */
+
+ usb_get_device_status(dev,&devstatus);
+
+ /*
+ * Set us to configuration index 0
+ */
+
+ usb_set_configuration(dev,cfgdscr->bConfigurationValue);
+
+ /*
+ * Get the hub descriptor. Get the first 8 bytes first, then get the rest
+ * if there is more.
+ */
+
+ if (usbhub_get_hub_descriptor(dev,&(softc->uhub_descr),0,USB_HUB_DESCR_SIZE) > USB_HUB_DESCR_SIZE) {
+ usbhub_get_hub_descriptor(dev,&(softc->uhub_descr),0,softc->uhub_descr.bDescriptorLength);
+ }
+
+ /*
+ * remember stuff from the hub descriptor
+ */
+
+ softc->uhub_nports = softc->uhub_descr.bNumberOfPorts;
+
+ /*
+ * Open the interrupt pipe
+ */
+
+ softc->uhub_ipipe = usb_open_pipe(dev,epdscr);
+ softc->uhub_ipipemps = GETUSBFIELD(epdscr,wMaxPacketSize);
+
+ /*
+ * Mark the bus and the hub as needing service.
+ */
+
+ softc->uhub_flags |= UHUB_FLG_NEEDSCAN;
+ dev->ud_bus->ub_flags |= UB_FLG_NEEDSCAN;
+
+ /*
+ * Okay, that's it. The top-level USB daemon will notice
+ * that the bus needs service and will invoke the exploration code.
+ * This may in turn require additional explores until
+ * everything settles down.
+ */
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * usbhub_detach(dev)
+ *
+ * Called when a hub is removed from the system - we remove
+ * all subordinate devicees.
+ *
+ * Input parameters:
+ * dev - device (hub) that was removed
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int usbhub_detach(usbdev_t *dev)
+{
+ usbhub_softc_t *hub;
+ usbdev_t *deldev;
+ int idx;
+
+ if (!IS_HUB(dev)) return 0; /* should not happen */
+
+ hub = dev->ud_private;
+ for (idx = 0; idx < UHUB_MAX_DEVICES; idx++) {
+ deldev = hub->uhub_devices[idx];
+ if (deldev) {
+ console_log("USB: Removing device attached to bus %d hub %d port %d",
+ dev->ud_bus->ub_num,
+ dev->ud_address,idx+1);
+ if (deldev->ud_drv) {
+ (*(deldev->ud_drv->udrv_detach))(deldev);
+ }
+ else {
+ if (usb_noisy > 0) {
+ console_log("USB: Detached device on bus %d hub %d port %d "
+ "has no methods",
+ dev->ud_bus->ub_num,
+ dev->ud_address,idx+1);
+ }
+ }
+ if (deldev->ud_cfgdescr) KFREE(deldev->ud_cfgdescr);
+ usb_destroy_device(deldev);
+ }
+ }
+
+ KFREE(hub); /* remove softc */
+
+ return 0;
+}
+
+
+
+/* *********************************************************************
+ * usbhub_map_tree1(dev,level,func,arg)
+ *
+ * This routine is used in recursive device tree exploration.
+ * We call 'func' for each device at this tree, and descend
+ * when we run into hubs
+ *
+ * Input parameters:
+ * dev - current device pointer
+ * level - current nesting level
+ * func - function to call
+ * arg - argument to pass to function
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void usbhub_map_tree1(usbdev_t *dev,int level,
+ int (*func)(usbdev_t *dev,void *arg),void *arg)
+{
+ usbhub_softc_t *hub;
+ int idx;
+
+ (*func)(dev,arg);
+
+ if (IS_HUB(dev)) {
+ hub = dev->ud_private;
+ for (idx = 0; idx < UHUB_MAX_DEVICES; idx++) {
+ if (hub->uhub_devices[idx]) {
+ usbhub_map_tree1(hub->uhub_devices[idx],level+1,func,arg);
+ }
+ }
+ }
+}
+
+/* *********************************************************************
+ * usbhub_map_tree(bus,func,arg)
+ *
+ * Call a function for each device in the tree
+ *
+ * Input parameters:
+ * bus - bus to scan
+ * func - function to call
+ * arg - argument to pass to function
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void usbhub_map_tree(usbbus_t *bus,int (*func)(usbdev_t *dev,void *arg),void *arg)
+{
+ usbhub_map_tree1(bus->ub_roothub,0,func,arg);
+}
+
+
+/* *********************************************************************
+ * usbhub_dumpbus1(dev,arg)
+ *
+ * map function to dump devices in the device tree
+ *
+ * Input parameters:
+ * dev - device we're working on
+ * arg - argument from map_tree call
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int usbhub_dumpbus1(usbdev_t *dev,void *arg)
+{
+ uint32_t *verbose = (uint32_t *) arg;
+
+ if ((*verbose & 0x00FF) && (dev->ud_address != (*verbose & 0x00FF))) return 0;
+
+ if (*verbose & 0x100) {
+ printf("============================================================================\n");
+ }
+
+ printf("Bus %d Device %d Class %d Vendor %04X Product %04X ",
+ dev->ud_bus->ub_num,
+ dev->ud_address,
+ dev->ud_devdescr.bDeviceClass,
+ GETUSBFIELD(&(dev->ud_devdescr),idVendor),
+ GETUSBFIELD(&(dev->ud_devdescr),idProduct));
+
+
+ if (IS_HUB(dev)) {
+ printf("[HUB]\n");
+ }
+ else {
+ printf("[DEVICE]\n");
+ }
+
+ if (*verbose & 0x100) {
+ usb_dbg_dumpdescriptors(dev,(uint8_t *) &(dev->ud_devdescr),dev->ud_devdescr.bLength);
+ usb_dbg_dumpcfgdescr(dev);
+ }
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * usbhub_dumpbus(bus,verbose)
+ *
+ * Dump information about devices on the USB bus.
+ *
+ * Input parameters:
+ * bus - bus to dump
+ * verbose - nonzero to display more info, like descriptors
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void usbhub_dumpbus(usbbus_t *bus,uint32_t verbose)
+{
+ usbhub_map_tree(bus,usbhub_dumpbus1,&verbose);
+}
+
+
+
+/* *********************************************************************
+ * usbhub_reset_devicee(dev,port,status)
+ *
+ * Reset a device on a hub port. This routine does a
+ * USB_PORT_FEATURE_RESET on the specified port, waits for the
+ * bit to clear, and returns. It is used to get a device into the
+ * DEFAULT state according to the spec.
+ *
+ * Input parameters:
+ * dev - hub device
+ * port - port number(1-based)
+ * status - place to return port_status structure after
+ * reset completes
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void usbhub_reset_device(usbdev_t *dev,int port,usb_port_status_t *portstatus)
+{
+ console_log("USB: Resetting device on bus %d port %d",dev->ud_bus->ub_num,port);
+#ifndef _CFE_
+ fflush(stdout);
+#endif
+
+ usbhub_set_port_feature(dev,port,USB_PORT_FEATURE_RESET);
+
+ usbhub_get_port_status(dev,port,portstatus);
+
+ for (;;) {
+ usbhub_get_port_status(dev,port,portstatus);
+ if ((GETUSBFIELD((portstatus),wPortStatus) & USB_PORT_STATUS_RESET) == 0) break;
+ usb_delay_ms(dev->ud_bus,250);
+ }
+ usb_delay_ms(dev->ud_bus,250);
+
+ usbhub_clear_port_feature(dev,port,USB_PORT_FEATURE_C_PORT_RESET);
+}
+
+
+
+/* *********************************************************************
+ * usbhub_scan_ports(dev,arg)
+ *
+ * Scan the ports on this hub for new or removed devices.
+ *
+ * Input parameters:
+ * dev - hub device
+ * arg - passed from bus scan main routines
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void usbhub_scan_ports(usbdev_t *dev,void *arg)
+{
+ uint16_t current;
+ uint16_t changed;
+ usbhub_softc_t *softc;
+ int idx;
+ int res;
+ int len;
+ uint8_t *buf;
+ usbdev_t *newdev;
+ usb_driver_t *newdrv;
+ int addr;
+ usb_port_status_t portstatus;
+ usb_config_descr_t cfgdescr;
+ unsigned int powerondelay;
+
+ if (!IS_HUB(dev)) return; /* should not happen. */
+
+ /*
+ * We know this is a hub. Get the softc back.
+ */
+
+ softc = (usbhub_softc_t *) dev->ud_private;
+
+ powerondelay = ((unsigned int) softc->uhub_descr.bPowerOnToPowerGood)*2 + 20;
+
+ /*
+ * Turn on the power to the ports whose power is not yet on.
+ */
+
+ for (idx = 0; idx < softc->uhub_nports; idx++) {
+
+ usbhub_get_port_status(dev,idx+1,&portstatus);
+
+ current = GETUSBFIELD((&portstatus),wPortStatus);
+ changed = GETUSBFIELD((&portstatus),wPortChange);
+ if (usb_noisy > 1) {
+ printf("BeforePowerup: port %d status %04X changed %04X\n",idx+1,current,changed);
+ }
+
+ if (!(current & USB_PORT_STATUS_POWER)) {
+ if (usb_noisy > 1) console_log("USB: Powering up bus %d port %d",
+ dev->ud_bus->ub_num,idx+1);
+ usbhub_set_port_feature(dev,idx+1,USB_PORT_FEATURE_POWER);
+ usb_delay_ms(dev->ud_bus,powerondelay);
+ }
+ }
+
+ /*
+ * Begin exploration at this level.
+ */
+
+ for (idx = 0; idx < softc->uhub_nports; idx++) {
+
+ usbhub_get_port_status(dev,idx+1,&portstatus);
+
+ current = GETUSBFIELD((&portstatus),wPortStatus);
+ changed = GETUSBFIELD((&portstatus),wPortChange);
+
+ if (usb_noisy > 0) {
+ printf("USB: Explore: Bus %d Hub %d port %d status %04X changed %04X\n",
+ dev->ud_bus->ub_num,
+ dev->ud_address,idx+1,current,changed);
+ usb_dbg_dumpportstatus(idx+1,&portstatus,1);
+ }
+
+
+// if (changed & USB_PORT_STATUS_RESET) {
+// usbhub_clear_port_feature(dev,idx+1,USB_PORT_FEATURE_C_PORT_RESET);
+// }
+
+ if (changed & USB_PORT_STATUS_ENABLED) {
+ usbhub_clear_port_feature(dev,idx+1,USB_PORT_FEATURE_C_PORT_ENABLE);
+ }
+
+ if (changed & USB_PORT_STATUS_CONNECT) {
+ /*
+ * A device was either connected or disconnected.
+ * Clear the status change first.
+ */
+
+ usbhub_clear_port_feature(dev,idx+1,USB_PORT_FEATURE_C_PORT_CONNECTION);
+
+ if (current & USB_PORT_STATUS_CONNECT) {
+
+ /*
+ * The device has been CONNECTED.
+ */
+
+ console_log("USB: New device connected to bus %d hub %d port %d",
+ dev->ud_bus->ub_num,
+ dev->ud_address,idx+1);
+
+ /*
+ * Reset the device. Reuse our old port status structure
+ * so we get the latest status. Some devices do not report
+ * lowspeed until they are reset.
+ */
+
+ usbhub_reset_device(dev,idx+1,&portstatus);
+ current = GETUSBFIELD((&portstatus),wPortStatus);
+ changed = GETUSBFIELD((&portstatus),wPortChange);
+
+ /*
+ * Create a device for this port.
+ */
+
+ newdev = usb_create_device(dev->ud_bus,(current & USB_PORT_STATUS_LOWSPD) ? 1 : 0);
+
+ /*
+ * Get the device descriptor.
+ */
+
+ res = usb_get_device_descriptor(newdev,&(newdev->ud_devdescr),TRUE);
+
+ if (usb_noisy > 0) usb_dbg_dumpdescriptors(newdev,(uint8_t *) &(newdev->ud_devdescr),8);
+
+ /*
+ * Set up the max packet size for the control endpoint,
+ * then get the rest of the descriptor.
+ */
+
+ usb_set_ep0mps(newdev,newdev->ud_devdescr.bMaxPacketSize0);
+ res = usb_get_device_descriptor(newdev,&(newdev->ud_devdescr),FALSE);
+
+ /*
+ * Obtain a new address and set the address of the
+ * root hub to this address.
+ */
+
+ addr = usb_new_address(newdev->ud_bus);
+ res = usb_set_address(newdev,addr);
+
+ /*
+ * Get the configuration descriptor and all the
+ * associated interface and endpoint descriptors.
+ */
+
+ res = usb_get_config_descriptor(newdev,&cfgdescr,0,
+ sizeof(usb_config_descr_t));
+ if (res != sizeof(usb_config_descr_t)) {
+ printf("[a]usb_get_config_descriptor returns %d\n",res);
+ }
+
+ len = GETUSBFIELD(&cfgdescr,wTotalLength);
+ buf = KMALLOC(len,0);
+
+ res = usb_get_config_descriptor(newdev,(usb_config_descr_t *)buf,0,len);
+ if (res != len) {
+ printf("[b]usb_get_config_descriptor returns %d\n",res);
+ }
+
+ newdev->ud_cfgdescr = (usb_config_descr_t *) buf;
+
+ if (usb_noisy > 0) usb_dbg_dumpdescriptors(newdev,buf,len);
+
+ /*
+ * Point the hub at the devices it owns
+ */
+
+ softc->uhub_devices[idx] = newdev;
+
+ /*
+ * Find the driver for this. It had better be the hub
+ * driver.
+ */
+
+ newdrv = usb_find_driver(newdev);
+
+ /*
+ * Call the attach method.
+ */
+
+ if (newdrv) {
+ dev->ud_drv = newdrv; /* remember driver dispatch in device */
+ (*(newdrv->udrv_attach))(newdev,newdrv);
+ }
+ }
+
+ else {
+
+ /*
+ * The device has been DISCONNECTED.
+ */
+
+ console_log("USB: Device disconnected from bus %d hub %d port %d",
+ dev->ud_bus->ub_num,
+ dev->ud_address,idx+1);
+
+ /*
+ * Recover pointer to device below hub and clear
+ * this pointer.
+ */
+
+ newdev = softc->uhub_devices[idx]; /* Get device pointer */
+ softc->uhub_devices[idx] = NULL; /* remove device from hub */
+
+ /*
+ * Deassign the USB device's address and then
+ * call detach method to free resources. Devices that
+ * do not have drivers will not have any methods.
+ */
+
+ if (newdev) {
+ if (newdev->ud_drv) {
+ (*(newdev->ud_drv->udrv_detach))(newdev);
+ }
+ else {
+ if (usb_noisy > 0) {
+ console_log("USB: Detached device on bus %d hub %d port %d "
+ "has no methods",
+ dev->ud_bus->ub_num,
+ dev->ud_address,idx+1);
+ }
+ }
+
+ if (newdev->ud_cfgdescr) KFREE(newdev->ud_cfgdescr);
+
+ usb_destroy_device(newdev);
+ }
+
+ }
+ }
+
+ }
+
+
+ /*
+ * Queue up a request for the interrupt pipe. This will catch further
+ * changes at this port.
+ */
+
+ usbhub_queue_intreq(dev,softc);
+
+}
+
+/* *********************************************************************
+ * usbhub_scan1(dev,arg)
+ *
+ * Scan one device at this level, or descend if we run into a hub
+ * This is part of the device discovery code.
+ *
+ * Input parameters:
+ * dev - current device, maybe a hub
+ * arg - passed from main scan routine
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+
+static int usbhub_scan1(usbdev_t *dev,void *arg)
+{
+ usbhub_softc_t *hub;
+
+ /*
+ * If the device is not a hub, we've reached the leaves of the
+ * tree.
+ */
+
+ if (!IS_HUB(dev)) return 0;
+
+ /*
+ * Otherwise, scan the ports on this hub.
+ */
+
+ hub = dev->ud_private;
+
+ if (hub->uhub_flags & UHUB_FLG_NEEDSCAN) {
+ hub->uhub_flags &= ~UHUB_FLG_NEEDSCAN;
+ usbhub_scan_ports(dev,arg);
+ }
+
+ return 0;
+}
+
+/* *********************************************************************
+ * usb_scan(bus)
+ *
+ * Scan the bus looking for new or removed devices
+ *
+ * Input parameters:
+ * bus - bus to scan
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void usb_scan(usbbus_t *bus)
+{
+ /*
+ * Call our tree walker with the scan function.
+ */
+
+ usbhub_map_tree(bus,usbhub_scan1,NULL);
+}
+
+
+
+
diff --git a/cfe/cfe/usb/usbmain.c b/cfe/cfe/usb/usbmain.c
new file mode 100644
index 0000000..c39a7f6
--- /dev/null
+++ b/cfe/cfe/usb/usbmain.c
@@ -0,0 +1,367 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Main Module File: usbmain.c
+ *
+ * Main module that invokes the top of the USB stack from CFE.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+#include "lib_queue.h"
+#include "lib_physio.h"
+
+#include "cfe_timer.h"
+#include "ui_command.h"
+
+#if CFG_PCI
+#include "pcireg.h"
+#include "pcivar.h"
+#endif
+
+#include "usbchap9.h"
+#include "usbd.h"
+
+#include "bsp_config.h"
+
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+extern usb_hcdrv_t ohci_driver; /* OHCI Driver dispatch */
+
+extern int ohcidebug; /* OHCI debug control */
+extern int usb_noisy; /* USBD debug control */
+
+int usb_init(void); /* forward */
+int ui_init_usbcmds(void); /* forward */
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+/*
+ * We keep track of the pointers to USB buses in globals.
+ * One entry in this array per USB bus (the Opti controller
+ * on the SWARM has two functions, so it's two buses)
+ */
+
+#define USB_MAX_BUS 4
+int usb_buscnt = 0;
+usbbus_t *usb_buses[USB_MAX_BUS];
+
+
+/* *********************************************************************
+ * usb_cfe_timer(arg)
+ *
+ * This routine is called periodically by CFE's timer routines
+ * to give the USB subsystem some time. Basically we scan
+ * for work to do to manage configuration updates, and handle
+ * interrupts from the USB controllers.
+ *
+ * Input parameters:
+ * arg - value we passed when the timer was initialized
+ * (not used)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void usb_cfe_timer(void *arg)
+{
+ int idx;
+ static int in_poll = 0;
+
+ /*
+ * We sometimes call the timer routines in here, which calls
+ * the polling loop. This code is not reentrant, so
+ * prevent us from running the interrupt routine or
+ * bus daemon while we are already in there.
+ */
+
+ if (in_poll) return;
+
+ /*
+ * Do not allow nested "interrupts."
+ */
+
+ in_poll = 1;
+
+ for (idx = 0; idx < usb_buscnt; idx++) {
+ if (usb_buses[idx]) {
+ usb_poll(usb_buses[idx]);
+ usb_daemon(usb_buses[idx]);
+ }
+ }
+
+ /*
+ * Okay to call polling again.
+ */
+
+ in_poll = 0;
+}
+
+
+/* *********************************************************************
+ * usb_init_one_ohci(addr)
+ *
+ * Initialize one USB controller.
+ *
+ * Input parameters:
+ * addr - physical address of OHCI registers
+ *
+ * Return value:
+ * 0 if ok
+ * else error
+ ********************************************************************* */
+static int usb_init_one_ohci(uint32_t addr)
+{
+ usbbus_t *bus;
+ int res;
+
+ bus = UBCREATE(&ohci_driver, addr);
+
+ if (bus == NULL) {
+ printf("USB: Could not create OHCI driver structure for controller at 0x%08X\n",addr);
+ return -1;
+ }
+
+ bus->ub_num = usb_buscnt;
+
+ res = UBSTART(bus);
+
+ if (res != 0) {
+ printf("USB: Could not init OHCI controller at 0x%08X\n",addr);
+ UBSTOP(bus);
+ return -1;
+ }
+ else {
+ usb_buses[usb_buscnt++] = bus;
+ usb_initroot(bus);
+ }
+
+ return 0;
+}
+
+#if CFG_PCI
+/* *********************************************************************
+ * usb_init_pci_ohci()
+ *
+ * Initialize all PCI-based OHCI controllers
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0 if ok
+ * else error
+ ********************************************************************* */
+static int usb_init_pci_ohci(void)
+{
+ int res;
+ pcitag_t tag;
+ uint32_t pciclass;
+ physaddr_t bar;
+ int idx;
+
+ idx = 0;
+
+ while (pci_find_class(PCI_CLASS_SERIALBUS,idx,&tag) == 0) {
+ pciclass = pci_conf_read(tag,PCI_CLASS_REG);
+ if ((PCI_SUBCLASS(pciclass) == PCI_SUBCLASS_SERIALBUS_USB) &&
+ (PCI_INTERFACE(pciclass) == 0x10)) {
+ bar = (physaddr_t) pci_conf_read(tag,PCI_MAPREG_START);
+ pci_tagprintf(tag,"OHCI USB controller found at %08X\n",(uint32_t) bar);
+
+ /* On the BCM1250, this sets the address to "match bits" mode,
+ which eliminates the need for byte swaps of data to/from the registers. */
+ bar |= 0x20000000;
+
+ res = usb_init_one_ohci(bar);
+ if (res < 0) break;
+ }
+ idx++;
+ }
+
+ return 0;
+}
+#endif
+
+
+
+/* *********************************************************************
+ * usb_init()
+ *
+ * Initialize the USB subsystem
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+int usb_init(void)
+{
+ static int initdone = 0;
+
+ if (initdone) {
+ printf("USB has already been initialized.\n");
+ return -1;
+ }
+
+ printf("Initializing USB.\n");
+
+ initdone = 1;
+
+ usb_buscnt = 0;
+
+#if CFG_PCI
+ usb_init_pci_ohci();
+#endif
+
+#if CFG_USB_OHCI_BASE
+ usb_init_one_ohci(CFG_USB_OHCI_BASE);
+#endif
+
+ cfe_bg_add(usb_cfe_timer,NULL);
+
+ return 0;
+}
+
+
+
+static int ui_cmd_usb_start(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int res = 0;
+
+ if (cmd_sw_isset(cmd,"-o")) ohcidebug++;
+ if (cmd_sw_isset(cmd,"-oo")) ohcidebug+=2;
+ if (cmd_sw_isset(cmd,"-u")) usb_noisy++;
+ if (cmd_sw_isset(cmd,"-uu")) usb_noisy+=2;
+
+ if (usb_buscnt == 0) {
+ res = usb_init();
+ }
+
+ return res;
+}
+
+
+static int ui_cmd_usb_show(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int busnum;
+ int devnum;
+ char *x;
+ int idx;
+ uint32_t arg;
+
+ x = cmd_getarg(cmd,1);
+ if (!x) devnum = 0;
+ else devnum = atoi(x);
+
+ x = cmd_getarg(cmd,0);
+ if (!x) x = "*";
+ busnum = atoi(x);
+
+ if (busnum >= usb_buscnt) {
+ printf("Invalid bus number, %d USB Buses currently configured.\n",usb_buscnt);
+ return -1;
+ }
+
+ arg = cmd_sw_isset(cmd,"-v") ? 0x100 : 0;
+ arg |= (devnum & 0xFF);
+
+ if (x[0] == '*') {
+ for (idx = 0; idx < usb_buscnt; idx++) {
+ usbhub_dumpbus(usb_buses[idx],arg);
+ }
+ }
+ else {
+ usbhub_dumpbus(usb_buses[busnum],arg);
+ }
+
+ return 0;
+
+}
+
+/* *********************************************************************
+ * ui_init_usbcmds(void)
+ *
+ * Initialize the USB commands
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+int ui_init_usbcmds(void)
+{
+ cmd_addcmd("usb init",
+ ui_cmd_usb_start,
+ NULL,
+ "Initialize the USB controller.",
+ "usb init",
+ "-o;OHCI debug messages|"
+ "-oo;more OHCI debug messages|"
+ "-u;USBD debug messages|"
+ "-uu;more USBD debug messages");
+
+
+ cmd_addcmd("show usb",
+ ui_cmd_usb_show,
+ NULL,
+ "Display devices connected to USB bus.",
+ "usb show [bus [device]]\n\n"
+ "Displays the configuration descriptors for devices connected to the USB\n"
+ "If you specify a bus, the entire bus is displayed. If you specify the\n"
+ "device number as well, only the specified device is displayed\n",
+ "-v;Display descriptors from the devices");
+
+ return 0;
+}
diff --git a/cfe/cfe/usb/usbmass.c b/cfe/cfe/usb/usbmass.c
new file mode 100644
index 0000000..ae3856d
--- /dev/null
+++ b/cfe/cfe/usb/usbmass.c
@@ -0,0 +1,1199 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * USB Mass-Storage driver File: usbmass.c
+ *
+ * This driver deals with mass-storage devices that support
+ * the SCSI Transparent command set and USB Bulk-Only protocol
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#ifndef _CFE_
+#include <stdio.h>
+#include <time.h>
+#include <memory.h>
+#include <stdint.h>
+#include "usbhack.h"
+#else
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+#include "cfe_timer.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+#include "cfe_error.h"
+#include "cfe_console.h"
+#endif
+
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "usbchap9.h"
+#include "usbd.h"
+
+/* *********************************************************************
+ * USB Mass-Storage class Constants
+ ********************************************************************* */
+
+#define USBMASS_CBI_PROTOCOL 0
+#define USBMASS_CBI_NOCOMPLETE_PROTOCOL 1
+#define USBMASS_BULKONLY_PROTOCOL 0x50
+
+#define USBMASS_SUBCLASS_RBC 0x01
+#define USBMASS_SUBCLASS_SFF8020 0x02
+#define USBMASS_SUBCLASS_QIC157 0x03
+#define USBMASS_SUBCLASS_UFI 0x04
+#define USBMASS_SUBCLASS_SFF8070 0x05
+#define USBMASS_SUBCLASS_SCSI 0x06
+
+#define USBMASS_CSW_PASS 0x00
+#define USBMASS_CSW_FAILED 0x01
+#define USBMASS_CSW_PHASEERR 0x02
+
+#define USBMASS_CBW_SIGNATURE 0x43425355
+#define USBMASS_CSW_SIGNATURE 0x53425355
+
+/* *********************************************************************
+ * USB Mass-Storage class Structures
+ ********************************************************************* */
+
+typedef struct usbmass_cbw_s {
+ uint8_t dCBWSignature0,dCBWSignature1,dCBWSignature2,dCBWSignature3;
+ uint8_t dCBWTag0,dCBWTag1,dCBWTag2,dCBWTag3;
+ uint8_t dCBWDataTransferLength0,dCBWDataTransferLength1,
+ dCBWDataTransferLength2,dCBWDataTransferLength3;
+ uint8_t bmCBWFlags;
+ uint8_t bCBWLUN;
+ uint8_t bCBWCBLength;
+ uint8_t CBWCB[16];
+} usbmass_cbw_t;
+
+typedef struct usbmass_csw_s {
+ uint8_t dCSWSignature0,dCSWSignature1,dCSWSignature2,dCSWSignature3;
+ uint8_t dCSWTag0,dCSWTag1,dCSWTag2,dCSWTag3;
+ uint8_t dCSWDataResidue0,dCSWDataResidue1,dCSWDataResidue2,dCSWDataResidue3;
+ uint8_t bCSWStatus;
+} usbmass_csw_t;
+
+#define GETCBWFIELD(s,f) ((uint32_t)((s)->f##0) | ((uint32_t)((s)->f##1) << 8) | \
+ ((uint32_t)((s)->f##2) << 16) | ((uint32_t)((s)->f##3) << 24))
+#define PUTCBWFIELD(s,f,v) (s)->f##0 = (v & 0xFF); \
+ (s)->f##1 = ((v)>>8 & 0xFF); \
+ (s)->f##2 = ((v)>>16 & 0xFF); \
+ (s)->f##3 = ((v)>>24 & 0xFF);
+
+
+int usbmass_request_sense(usbdev_t *dev);
+
+/* *********************************************************************
+ * Linkage to CFE
+ ********************************************************************* */
+
+#ifdef _CFE_
+
+/*
+ * Softc for the CFE side of the disk driver.
+ */
+#define MAX_SECTORSIZE 2048
+typedef struct usbdisk_s {
+ uint32_t usbdisk_sectorsize;
+ uint32_t usbdisk_ttlsect;
+ uint32_t usbdisk_devtype;
+ int usbdisk_unit;
+} usbdisk_t;
+
+/*
+ * This table points at the currently configured USB disk
+ * devices. This lets us leave the CFE half of the driver lying
+ * around while the USB devices come and go. We use the unit number
+ * from the original CFE attach to index this table, and devices
+ * that are not present are "not ready."
+ */
+
+#define USBDISK_MAXUNITS 4
+static usbdev_t *usbdisk_units[USBDISK_MAXUNITS];
+
+/*
+ * CFE device driver routine forwards
+ */
+
+static void usbdisk_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+static int usbdisk_open(cfe_devctx_t *ctx);
+static int usbdisk_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int usbdisk_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int usbdisk_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int usbdisk_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int usbdisk_close(cfe_devctx_t *ctx);
+
+/*
+ * CFE device driver descriptor
+ */
+
+const static cfe_devdisp_t usbdisk_dispatch = {
+ usbdisk_open,
+ usbdisk_read,
+ usbdisk_inpstat,
+ usbdisk_write,
+ usbdisk_ioctl,
+ usbdisk_close,
+ NULL,
+ NULL
+};
+
+const cfe_driver_t usb_disk = {
+ "USB Disk",
+ "usbdisk",
+ CFE_DEV_DISK,
+ &usbdisk_dispatch,
+ usbdisk_probe
+};
+
+
+#endif
+
+
+
+/* *********************************************************************
+ * Forward Definitions
+ ********************************************************************* */
+
+static int usbmass_attach(usbdev_t *dev,usb_driver_t *drv);
+static int usbmass_detach(usbdev_t *dev);
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef struct usbmass_softc_s {
+ int umass_inpipe;
+ int umass_outpipe;
+ int umass_devtype;
+ uint32_t umass_curtag;
+ int umass_unit;
+} usbmass_softc_t;
+
+usb_driver_t usbmass_driver = {
+ "Mass-Storage Device",
+ usbmass_attach,
+ usbmass_detach
+};
+
+usbdev_t *usbmass_dev = NULL; /* XX hack for testing only */
+
+/* *********************************************************************
+ * usbmass_mass_storage_reset(dev,ifc)
+ *
+ * Do a bulk-only mass-storage reset.
+ *
+ * Input parameters:
+ * dev - device to reset
+ * ifc - interface number to reset (bInterfaceNum)
+ *
+ * Return value:
+ * status
+ ********************************************************************* */
+
+#define usbmass_mass_storage_reset(dev,ifc) \
+ usb_simple_request(dev,0x21,0xFF,ifc,0)
+
+#if 0
+/* *********************************************************************
+ * usbmass_get_max_lun(dev,lunp)
+ *
+ * Get maximum LUN from device
+ *
+ * Input parameters:
+ * dev - device to reset
+ * lunp - pointer to int to receive max lun
+ *
+ * Return value:
+ * status
+ ********************************************************************* */
+
+static int usbmass_get_max_lun(usbdev_t *dev,int *lunp)
+{
+ uint8_t buf = 0;
+ int res;
+
+ res = usb_std_request(dev,0xA1,0xFE,0,0,&buf,1);
+
+ if (res < 0) return res;
+
+ if (lunp) *lunp = (int) buf;
+ return 0;
+}
+
+#endif
+
+
+/* *********************************************************************
+ * usbmass_stall_recovery(dev)
+ *
+ * Do whatever it takes to unstick a stalled mass-storage device.
+ *
+ * Input parameters:
+ * dev - usb device
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void usbmass_stall_recovery(usbdev_t *dev)
+{
+ usbmass_softc_t *softc;
+
+ softc = (usbmass_softc_t *) dev->ud_private;
+
+ usb_clear_stall(dev,softc->umass_inpipe);
+
+ usbmass_request_sense(dev);
+}
+
+
+/* *********************************************************************
+ * usbmass_read_capacity(dev,sectornum,buffer)
+ *
+ * Reads a sector from the device.
+ *
+ * Input parameters:
+ * dev - usb device
+ * sectornum - sector number to read
+ * buffer - place to put sector we read
+ *
+ * Return value:
+ * status
+ ********************************************************************* */
+
+int usbmass_request_sense(usbdev_t *dev)
+{
+ uint8_t *cbwcsw;
+ uint8_t *sector;
+ usbmass_cbw_t *cbw;
+ usbmass_csw_t *csw;
+ usbreq_t *ur;
+ usbmass_softc_t *softc;
+ int res;
+
+ softc = (usbmass_softc_t *) dev->ud_private;
+
+ cbwcsw = KMALLOC(64,32);
+ sector = KMALLOC(64,32);
+
+ memset(sector,0,64);
+
+ cbw = (usbmass_cbw_t *) cbwcsw;
+ csw = (usbmass_csw_t *) cbwcsw;
+
+ /*
+ * Fill in the fields of the CBW
+ */
+
+ PUTCBWFIELD(cbw,dCBWSignature,USBMASS_CBW_SIGNATURE);
+ PUTCBWFIELD(cbw,dCBWTag,softc->umass_curtag);
+ PUTCBWFIELD(cbw,dCBWDataTransferLength,18);
+ cbw->bmCBWFlags = 0x80; /* IN */
+ cbw->bCBWLUN = 0;
+ cbw->bCBWCBLength = 12;
+ cbw->CBWCB[0] = 0x3; /* REQUEST SENSE */
+ cbw->CBWCB[1] = 0;
+ cbw->CBWCB[2] = 0;
+ cbw->CBWCB[3] = 0;
+ cbw->CBWCB[4] = 18; /* allocation length */
+ cbw->CBWCB[5] = 0;
+ cbw->CBWCB[6] = 0;
+ cbw->CBWCB[7] = 0;
+ cbw->CBWCB[8] = 0;
+ cbw->CBWCB[9] = 0;
+
+ softc->umass_curtag++;
+
+ /*
+ * Send the CBW
+ */
+
+ ur = usb_make_request(dev,softc->umass_outpipe,(uint8_t *) cbw,
+ sizeof(usbmass_cbw_t),UR_FLAG_OUT);
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+
+ /*
+ * Get the data
+ */
+
+ memset(sector,0,18);
+ ur = usb_make_request(dev,softc->umass_inpipe,sector,
+ 18,UR_FLAG_IN | UR_FLAG_SHORTOK);
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+
+ /*
+ * Get the Status
+ */
+
+ memset(csw,0,sizeof(usbmass_csw_t));
+ ur = usb_make_request(dev,softc->umass_inpipe,(uint8_t *) csw,
+ sizeof(usbmass_csw_t),UR_FLAG_IN);
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+
+ KFREE(cbwcsw);
+
+ KFREE(sector);
+
+ return 0;
+
+}
+
+/* *********************************************************************
+ * usbmass_read_sector(dev,sectornum,seccnt,buffer)
+ *
+ * Reads a sector from the device.
+ *
+ * Input parameters:
+ * dev - usb device
+ * sectornum - sector number to read
+ * seccnt - count of sectors to read
+ * buffer - place to put sector we read
+ *
+ * Return value:
+ * status
+ ********************************************************************* */
+
+int usbmass_read_sector(usbdev_t *dev,uint32_t sectornum,uint32_t seccnt,
+ uint8_t *buffer);
+int usbmass_read_sector(usbdev_t *dev,uint32_t sectornum,uint32_t seccnt,
+ uint8_t *buffer)
+{
+ uint8_t *cbwcsw;
+ uint8_t *sector;
+ usbmass_cbw_t *cbw;
+ usbmass_csw_t *csw;
+ usbreq_t *ur;
+ usbmass_softc_t *softc;
+ int res;
+
+ softc = (usbmass_softc_t *) dev->ud_private;
+
+ cbwcsw = KMALLOC(64,32);
+ sector = buffer;
+
+ cbw = (usbmass_cbw_t *) cbwcsw;
+ csw = (usbmass_csw_t *) cbwcsw;
+
+ /*
+ * Fill in the fields of the CBW
+ */
+
+ PUTCBWFIELD(cbw,dCBWSignature,USBMASS_CBW_SIGNATURE);
+ PUTCBWFIELD(cbw,dCBWTag,softc->umass_curtag);
+ PUTCBWFIELD(cbw,dCBWDataTransferLength,(512*seccnt));
+ cbw->bmCBWFlags = 0x80; /* IN */
+ cbw->bCBWLUN = 0;
+ cbw->bCBWCBLength = 10;
+ cbw->CBWCB[0] = 0x28; /* READ */
+ cbw->CBWCB[1] = 0;
+ cbw->CBWCB[2] = (sectornum >> 24) & 0xFF; /* LUN 0 & MSB's of sector */
+ cbw->CBWCB[3] = (sectornum >> 16) & 0xFF;
+ cbw->CBWCB[4] = (sectornum >> 8) & 0xFF;
+ cbw->CBWCB[5] = (sectornum >> 0) & 0xFF;
+ cbw->CBWCB[6] = 0;
+ cbw->CBWCB[7] = 0;
+ cbw->CBWCB[8] = seccnt;
+ cbw->CBWCB[9] = 0;
+
+ softc->umass_curtag++;
+
+ /*
+ * Send the CBW
+ */
+
+ ur = usb_make_request(dev,softc->umass_outpipe,(uint8_t *) cbw,
+ sizeof(usbmass_cbw_t),UR_FLAG_OUT);
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+ if (res == 4) {
+ usbmass_stall_recovery(dev);
+ KFREE(cbwcsw);
+ return -1;
+ }
+
+
+ /*
+ * Get the data
+ */
+
+ ur = usb_make_request(dev,softc->umass_inpipe,sector,
+ 512*seccnt,UR_FLAG_IN | UR_FLAG_SHORTOK);
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+ if (res == 4) {
+ usbmass_stall_recovery(dev);
+ KFREE(cbwcsw);
+ return -1;
+ }
+
+
+ /*
+ * Get the Status
+ */
+
+ memset(csw,0,sizeof(usbmass_csw_t));
+ ur = usb_make_request(dev,softc->umass_inpipe,(uint8_t *) csw,
+ sizeof(usbmass_csw_t),UR_FLAG_IN);
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+ if (res == 4) {
+ usbmass_stall_recovery(dev);
+ KFREE(cbwcsw);
+ return -1;
+ }
+
+
+#if 0
+ printf("CSW: Signature=%08X Tag=%08X Residue=%08X Status=%02X\n",
+ GETCBWFIELD(csw,dCSWSignature),
+ GETCBWFIELD(csw,dCSWTag),
+ GETCBWFIELD(csw,dCSWDataResidue),
+ csw->bCSWStatus);
+#endif
+
+ res = (csw->bCSWStatus == USBMASS_CSW_PASS) ? 0 : -1;
+
+ KFREE(cbwcsw);
+
+ return res;
+
+}
+
+/* *********************************************************************
+ * usbmass_write_sector(dev,sectornum,seccnt,buffer)
+ *
+ * Writes a sector to the device
+ *
+ * Input parameters:
+ * dev - usb device
+ * sectornum - sector number to write
+ * seccnt - count of sectors to write
+ * buffer - place to get sector to write
+ *
+ * Return value:
+ * status
+ ********************************************************************* */
+
+static int usbmass_write_sector(usbdev_t *dev,uint32_t sectornum,uint32_t seccnt,
+ uint8_t *buffer)
+{
+ uint8_t *cbwcsw;
+ uint8_t *sector;
+ usbmass_cbw_t *cbw;
+ usbmass_csw_t *csw;
+ usbreq_t *ur;
+ usbmass_softc_t *softc;
+ int res;
+
+ softc = (usbmass_softc_t *) dev->ud_private;
+
+ cbwcsw = KMALLOC(64,32);
+ sector = buffer;
+
+ cbw = (usbmass_cbw_t *) cbwcsw;
+ csw = (usbmass_csw_t *) cbwcsw;
+
+ /*
+ * Fill in the fields of the CBW
+ */
+
+ PUTCBWFIELD(cbw,dCBWSignature,USBMASS_CBW_SIGNATURE);
+ PUTCBWFIELD(cbw,dCBWTag,softc->umass_curtag);
+ PUTCBWFIELD(cbw,dCBWDataTransferLength,(512*seccnt));
+ cbw->bmCBWFlags = 0x00; /* OUT */
+ cbw->bCBWLUN = 0;
+ cbw->bCBWCBLength = 10;
+ cbw->CBWCB[0] = 0x2A; /* WRITE */
+ cbw->CBWCB[1] = 0;
+ cbw->CBWCB[2] = (sectornum >> 24) & 0xFF; /* LUN 0 & MSB's of sector */
+ cbw->CBWCB[3] = (sectornum >> 16) & 0xFF;
+ cbw->CBWCB[4] = (sectornum >> 8) & 0xFF;
+ cbw->CBWCB[5] = (sectornum >> 0) & 0xFF;
+ cbw->CBWCB[6] = 0;
+ cbw->CBWCB[7] = 0;
+ cbw->CBWCB[8] = seccnt;
+ cbw->CBWCB[9] = 0;
+
+ softc->umass_curtag++;
+
+ /*
+ * Send the CBW
+ */
+
+ ur = usb_make_request(dev,softc->umass_outpipe,(uint8_t *) cbw,
+ sizeof(usbmass_cbw_t),UR_FLAG_OUT);
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+
+ /*
+ * Send the data
+ */
+
+ ur = usb_make_request(dev,softc->umass_outpipe,sector,
+ 512*seccnt,UR_FLAG_OUT);
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+
+ /*
+ * Get the Status
+ */
+
+ memset(csw,0,sizeof(usbmass_csw_t));
+ ur = usb_make_request(dev,softc->umass_inpipe,(uint8_t *) csw,
+ sizeof(usbmass_csw_t),UR_FLAG_IN);
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+
+#if 0
+ printf("CSW: Signature=%08X Tag=%08X Residue=%08X Status=%02X\n",
+ GETCBWFIELD(csw,dCSWSignature),
+ GETCBWFIELD(csw,dCSWTag),
+ GETCBWFIELD(csw,dCSWDataResidue),
+ csw->bCSWStatus);
+#endif
+
+ res = (csw->bCSWStatus == USBMASS_CSW_PASS) ? 0 : -1;
+
+ KFREE(cbwcsw);
+
+ return res;
+}
+
+/* *********************************************************************
+ * usbmass_read_capacity(dev,sectornum,buffer)
+ *
+ * Reads a sector from the device.
+ *
+ * Input parameters:
+ * dev - usb device
+ * sectornum - sector number to read
+ * buffer - place to put sector we read
+ *
+ * Return value:
+ * status
+ ********************************************************************* */
+
+int usbmass_read_capacity(usbdev_t *dev,uint32_t *size);
+int usbmass_read_capacity(usbdev_t *dev,uint32_t *size)
+{
+ uint8_t *cbwcsw;
+ uint8_t *sector;
+ usbmass_cbw_t *cbw;
+ usbmass_csw_t *csw;
+ usbreq_t *ur;
+ usbmass_softc_t *softc;
+ int res;
+
+ softc = (usbmass_softc_t *) dev->ud_private;
+
+ cbwcsw = KMALLOC(64,32);
+ sector = KMALLOC(64,32);
+
+ memset(sector,0,64);
+
+ cbw = (usbmass_cbw_t *) cbwcsw;
+ csw = (usbmass_csw_t *) cbwcsw;
+
+ *size = 0;
+
+ /*
+ * Fill in the fields of the CBW
+ */
+
+ PUTCBWFIELD(cbw,dCBWSignature,USBMASS_CBW_SIGNATURE);
+ PUTCBWFIELD(cbw,dCBWTag,softc->umass_curtag);
+ PUTCBWFIELD(cbw,dCBWDataTransferLength,8);
+ cbw->bmCBWFlags = 0x80; /* IN */
+ cbw->bCBWLUN = 0;
+ cbw->bCBWCBLength = 10;
+ cbw->CBWCB[0] = 0x25; /* READ CAPACITY */
+ cbw->CBWCB[1] = 0;
+ cbw->CBWCB[2] = 0;
+ cbw->CBWCB[3] = 0;
+ cbw->CBWCB[4] = 0;
+ cbw->CBWCB[5] = 0;
+ cbw->CBWCB[6] = 0;
+ cbw->CBWCB[7] = 0;
+ cbw->CBWCB[8] = 0;
+ cbw->CBWCB[9] = 0;
+
+ softc->umass_curtag++;
+
+ /*
+ * Send the CBW
+ */
+
+ ur = usb_make_request(dev,softc->umass_outpipe,(uint8_t *) cbw,
+ sizeof(usbmass_cbw_t),UR_FLAG_OUT);
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+
+ if (res == 4) {
+ usbmass_stall_recovery(dev);
+ KFREE(cbwcsw);
+ KFREE(sector);
+ return -1;
+ }
+
+ /*
+ * Get the data
+ */
+
+ ur = usb_make_request(dev,softc->umass_inpipe,sector,
+ 8,UR_FLAG_IN | UR_FLAG_SHORTOK);
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+
+ if (res == 4) {
+ usbmass_stall_recovery(dev);
+ KFREE(cbwcsw);
+ KFREE(sector);
+ return -1;
+ }
+
+ /*
+ * Get the Status
+ */
+
+ memset(csw,0,sizeof(usbmass_csw_t));
+ ur = usb_make_request(dev,softc->umass_inpipe,(uint8_t *) csw,
+ sizeof(usbmass_csw_t),UR_FLAG_IN);
+ res = usb_sync_request(ur);
+ usb_free_request(ur);
+
+ KFREE(cbwcsw);
+
+ *size = (((uint32_t) sector[0]) << 24) |
+ (((uint32_t) sector[1]) << 16) |
+ (((uint32_t) sector[2]) << 8) |
+ (((uint32_t) sector[3]) << 0);
+
+ KFREE(sector);
+
+ return 0;
+
+}
+
+
+
+/* *********************************************************************
+ * usbmass_attach(dev,drv)
+ *
+ * This routine is called when the bus scan stuff finds a mass-storage
+ * device. We finish up the initialization by configuring the
+ * device and allocating our softc here.
+ *
+ * Input parameters:
+ * dev - usb device, in the "addressed" state.
+ * drv - the driver table entry that matched
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int usbmass_attach(usbdev_t *dev,usb_driver_t *drv)
+{
+ usb_config_descr_t *cfgdscr = dev->ud_cfgdescr;
+ usb_endpoint_descr_t *epdscr;
+ usb_endpoint_descr_t *indscr = NULL;
+ usb_endpoint_descr_t *outdscr = NULL;
+ usb_interface_descr_t *ifdscr;
+ usbmass_softc_t *softc;
+ int idx;
+
+ dev->ud_drv = drv;
+
+ softc = KMALLOC(sizeof(usbmass_softc_t),0);
+ memset(softc,0,sizeof(usbmass_softc_t));
+ dev->ud_private = softc;
+
+ ifdscr = usb_find_cfg_descr(dev,USB_INTERFACE_DESCRIPTOR_TYPE,0);
+ if (ifdscr == NULL) {
+ return -1;
+ }
+
+ if ((ifdscr->bInterfaceSubClass != USBMASS_SUBCLASS_SCSI) ||
+ (ifdscr->bInterfaceProtocol != USBMASS_BULKONLY_PROTOCOL)) {
+ console_log("USBMASS: Do not understand devices with SubClass 0x%02X, Protocol 0x%02X",
+ ifdscr->bInterfaceSubClass,
+ ifdscr->bInterfaceProtocol);
+ return -1;
+ }
+
+ for (idx = 0; idx < 2; idx++) {
+ epdscr = usb_find_cfg_descr(dev,USB_ENDPOINT_DESCRIPTOR_TYPE,idx);
+
+ if (USB_ENDPOINT_DIR_OUT(epdscr->bEndpointAddress)) {
+ outdscr = epdscr;
+ }
+ else {
+ indscr = epdscr;
+ }
+ }
+
+
+ if (!indscr || !outdscr) {
+ /*
+ * Could not get descriptors, something is very wrong.
+ * Leave device addressed but not configured.
+ */
+ return -1;
+ }
+
+ /*
+ * Choose the standard configuration.
+ */
+
+ usb_set_configuration(dev,cfgdscr->bConfigurationValue);
+
+ /*
+ * Open the pipes.
+ */
+
+ softc->umass_inpipe = usb_open_pipe(dev,indscr);
+ softc->umass_outpipe = usb_open_pipe(dev,outdscr);
+ softc->umass_curtag = 0x12345678;
+
+ /*
+ * Save pointer in global unit table so we can
+ * match CFE devices up with USB ones
+ */
+
+
+#ifdef _CFE_
+ softc->umass_unit = -1;
+ for (idx = 0; idx < USBDISK_MAXUNITS; idx++) {
+ if (usbdisk_units[idx] == NULL) {
+ softc->umass_unit = idx;
+ usbdisk_units[idx] = dev;
+ break;
+ }
+ }
+
+ console_log("USBMASS: Unit %d connected",softc->umass_unit);
+#endif
+
+ usbmass_dev = dev;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * usbmass_detach(dev)
+ *
+ * This routine is called when the bus scanner notices that
+ * this device has been removed from the system. We should
+ * do any cleanup that is required. The pending requests
+ * will be cancelled automagically.
+ *
+ * Input parameters:
+ * dev - usb device
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int usbmass_detach(usbdev_t *dev)
+{
+ usbmass_softc_t *softc;
+ softc = (usbmass_softc_t *) dev->ud_private;
+
+#ifdef _CFE_
+ console_log("USBMASS: USB unit %d disconnected",softc->umass_unit);
+ if (softc->umass_unit >= 0) usbdisk_units[softc->umass_unit] = NULL;
+#endif
+
+ KFREE(softc);
+ return 0;
+}
+
+
+
+#ifdef _CFE_
+
+
+/* *********************************************************************
+ * usbdisk_sectorshift(size)
+ *
+ * Given a sector size, return log2(size). We cheat; this is
+ * only needed for 2048 and 512-byte sectors.
+ * Explicitly using shifts and masks in sector number calculations
+ * helps on 32-bit-only platforms, since we probably won't need
+ * a helper library.
+ *
+ * Input parameters:
+ * size - sector size
+ *
+ * Return value:
+ * # of bits to shift
+ ********************************************************************* */
+
+#define usbdisk_sectorshift(size) (((size)==2048)?11:9)
+
+
+/* *********************************************************************
+ * usbdisk_probe(drv,probe_a,probe_b,probe_ptr)
+ *
+ * Our probe routine. Attach an empty USB disk device to the firmware.
+ *
+ * Input parameters:
+ * drv - driver structure
+ * probe_a - not used
+ * probe_b - not used
+ * probe_ptr - not used
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void usbdisk_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ usbdisk_t *softc;
+ char descr[128];
+
+ softc = (usbdisk_t *) KMALLOC(sizeof(usbdisk_t),0);
+
+ memset(softc,0,sizeof(usbdisk_t));
+
+ softc->usbdisk_sectorsize = 512;
+ softc->usbdisk_devtype = BLOCK_DEVTYPE_DISK;
+ softc->usbdisk_ttlsect = 0; /* not calculated yet */
+ softc->usbdisk_unit = (int)probe_a;
+
+ xsprintf(descr,"USB Disk unit %d",(int)probe_a);
+
+ cfe_attach(drv,softc,NULL,descr);
+}
+
+
+/* *********************************************************************
+ * usbdisk_open(ctx)
+ *
+ * Process the CFE OPEN call for this device. For IDE disks,
+ * the device is reset and identified, and the geometry is
+ * determined.
+ *
+ * Input parameters:
+ * ctx - device context
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+
+static int usbdisk_open(cfe_devctx_t *ctx)
+{
+ usbdisk_t *softc = ctx->dev_softc;
+ usbdev_t *dev = usbdisk_units[softc->usbdisk_unit];
+ uint32_t size;
+ int res;
+
+ if (!dev) return CFE_ERR_NOTREADY;
+
+ usbmass_request_sense(dev);
+
+ res = usbmass_read_capacity(dev,&size);
+ if (res < 0) return res;
+
+ softc->usbdisk_ttlsect = size;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * usbdisk_read(ctx,buffer)
+ *
+ * Process a CFE READ command for the IDE device. This is
+ * more complex than it looks, since CFE offsets are byte offsets
+ * and we may need to read partial sectors.
+ *
+ * Input parameters:
+ * ctx - device context
+ * buffer - buffer descriptor
+ *
+ * Return value:
+ * number of bytes read, or <0 if an error occured
+ ********************************************************************* */
+
+static int usbdisk_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ usbdisk_t *softc = ctx->dev_softc;
+ usbdev_t *dev = usbdisk_units[softc->usbdisk_unit];
+ unsigned char *bptr;
+ int blen;
+ int numsec;
+ int res = 0;
+ int amtcopy;
+ uint64_t lba;
+ uint64_t offset;
+ unsigned char sector[MAX_SECTORSIZE];
+ int sectorshift;
+
+ if (!dev) return CFE_ERR_NOTREADY;
+
+ sectorshift = usbdisk_sectorshift(softc->usbdisk_sectorsize);
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+ offset = buffer->buf_offset;
+ numsec = (blen + softc->usbdisk_sectorsize - 1) >> sectorshift;
+
+ if (offset & (softc->usbdisk_sectorsize-1)) {
+ lba = (offset >> sectorshift);
+ res = usbmass_read_sector(dev,lba,1,sector);
+ if (res < 0) goto out;
+ amtcopy = softc->usbdisk_sectorsize - (offset & (softc->usbdisk_sectorsize-1));
+ if (amtcopy > blen) amtcopy = blen;
+ memcpy(bptr,&sector[offset & (softc->usbdisk_sectorsize-1)],amtcopy);
+ bptr += amtcopy;
+ offset += amtcopy;
+ blen -= amtcopy;
+ }
+
+ if (blen >= softc->usbdisk_sectorsize) {
+ int seccnt;
+
+ lba = (offset >> sectorshift);
+ seccnt = (blen >> sectorshift);
+
+ res = usbmass_read_sector(dev,lba,seccnt,bptr);
+ if (res < 0) goto out;
+
+ amtcopy = seccnt << sectorshift;
+ bptr += amtcopy;
+ offset += amtcopy;
+ blen -= amtcopy;
+ }
+
+ if (blen) {
+ lba = (offset >> sectorshift);
+ res = usbmass_read_sector(dev,lba,1,sector);
+ if (res < 0) goto out;
+ amtcopy = blen;
+ memcpy(bptr,sector,amtcopy);
+ bptr += amtcopy;
+ offset += amtcopy;
+ blen -= amtcopy;
+ }
+
+out:
+ buffer->buf_retlen = bptr - buffer->buf_ptr;
+
+ return res;
+}
+
+/* *********************************************************************
+ * usbdisk_inpstat(ctx,inpstat)
+ *
+ * Test input status for the IDE disk. Disks are always ready
+ * to read.
+ *
+ * Input parameters:
+ * ctx - device context
+ * inpstat - input status structure
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int usbdisk_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
+{
+ /* usbdisk_t *softc = ctx->dev_softc; */
+
+ inpstat->inp_status = 1;
+ return 0;
+}
+
+/* *********************************************************************
+ * usbdisk_write(ctx,buffer)
+ *
+ * Process a CFE WRITE command for the IDE device. If the write
+ * involves partial sectors, the affected sectors are read first
+ * and the changes are merged in.
+ *
+ * Input parameters:
+ * ctx - device context
+ * buffer - buffer descriptor
+ *
+ * Return value:
+ * number of bytes write, or <0 if an error occured
+ ********************************************************************* */
+
+static int usbdisk_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ usbdisk_t *softc = ctx->dev_softc;
+ usbdev_t *dev = usbdisk_units[softc->usbdisk_unit];
+ unsigned char *bptr;
+ int blen;
+ int numsec;
+ int res = 0;
+ int amtcopy;
+ uint64_t offset;
+ uint64_t lba;
+ unsigned char sector[MAX_SECTORSIZE];
+ int sectorshift;
+
+ if (!dev) return CFE_ERR_NOTREADY;
+
+ sectorshift = usbdisk_sectorshift(softc->usbdisk_sectorsize);
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+ offset = buffer->buf_offset;
+ numsec = (blen + softc->usbdisk_sectorsize - 1) >> sectorshift;
+
+ if (offset & (softc->usbdisk_sectorsize-1)) {
+ lba = (offset >> sectorshift);
+ res = usbmass_read_sector(dev,lba,1,sector);
+ if (res < 0) goto out;
+ amtcopy = softc->usbdisk_sectorsize - (offset & (softc->usbdisk_sectorsize-1));
+ if (amtcopy > blen) amtcopy = blen;
+ memcpy(&sector[offset & (softc->usbdisk_sectorsize-1)],bptr,amtcopy);
+ res = usbmass_write_sector(dev,lba,1,sector);
+ if (res < 0) goto out;
+ bptr += amtcopy;
+ offset += amtcopy;
+ blen -= amtcopy;
+ }
+
+ while (blen >= softc->usbdisk_sectorsize) {
+ amtcopy = softc->usbdisk_sectorsize;
+ lba = (offset >> sectorshift);
+ res = usbmass_write_sector(dev,lba,1,bptr);
+ if (res < 0) goto out;
+ bptr += amtcopy;
+ offset += amtcopy;
+ blen -= amtcopy;
+ }
+
+ if (blen) {
+ lba = (offset >> sectorshift);
+ res = usbmass_read_sector(dev,lba,1,sector);
+ if (res < 0) goto out;
+ amtcopy = blen;
+ memcpy(sector,bptr,amtcopy);
+ res = usbmass_write_sector(dev,lba,1,sector);
+ if (res < 0) goto out;
+ bptr += amtcopy;
+ offset += amtcopy;
+ blen -= amtcopy;
+ }
+
+out:
+ buffer->buf_retlen = bptr - buffer->buf_ptr;
+
+ return res;
+}
+
+
+/* *********************************************************************
+ * usbdisk_ioctl(ctx,buffer)
+ *
+ * Process device I/O control requests for the IDE device.
+ *
+ * Input parameters:
+ * ctx - device context
+ * buffer - buffer descriptor
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int usbdisk_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ usbdisk_t *softc = ctx->dev_softc;
+ unsigned int *info = (unsigned int *) buffer->buf_ptr;
+ unsigned long long *linfo = (unsigned long long *) buffer->buf_ptr;
+ blockdev_info_t *devinfo;
+
+ switch ((int)buffer->buf_ioctlcmd) {
+ case IOCTL_BLOCK_GETBLOCKSIZE:
+ *info = softc->usbdisk_sectorsize;
+ break;
+ case IOCTL_BLOCK_GETTOTALBLOCKS:
+ *linfo = softc->usbdisk_ttlsect;
+ break;
+ case IOCTL_BLOCK_GETDEVTYPE:
+ devinfo = (blockdev_info_t *) buffer->buf_ptr;
+ devinfo->blkdev_totalblocks = softc->usbdisk_ttlsect;
+ devinfo->blkdev_blocksize = softc->usbdisk_sectorsize;
+ devinfo->blkdev_devtype = softc->usbdisk_devtype;
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+/* *********************************************************************
+ * usbdisk_close(ctx)
+ *
+ * Close the I/O device.
+ *
+ * Input parameters:
+ * ctx - device context
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+static int usbdisk_close(cfe_devctx_t *ctx)
+{
+ /* usbdisk_t *softc = ctx->dev_softc; */
+
+ return 0;
+}
+
+
+#endif
diff --git a/cfe/cfe/usb/usbserial.c b/cfe/cfe/usb/usbserial.c
new file mode 100644
index 0000000..737d8b4
--- /dev/null
+++ b/cfe/cfe/usb/usbserial.c
@@ -0,0 +1,713 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * USB Serial Port Driver File: usbserial.c
+ *
+ * This device can talk to a few of those usb->serial converters
+ * out there.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#ifndef _CFE_
+#include <stdio.h>
+#include <time.h>
+#include <memory.h>
+#include <stdint.h>
+#include "usbhack.h"
+#else
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+#include "cfe_console.h"
+#include "bsp_config.h"
+#endif
+
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "usbchap9.h"
+#include "usbd.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define USER_FIFOSIZE 256
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef struct usbser_linedata_s {
+ uint8_t dLineDataBaud0,dLineDataBaud1,dLineDataBaud2,dLineDataBaud3;
+ uint8_t bLineDataStopBits; /* 0=1, 1=1.5, 2=2 */
+ uint8_t bLineDataParity; /* 0=none, 1=odd, 2=even, 3=mark, 4=space */
+ uint8_t bLineDataBits; /* 5,6,7,8 */
+} usbser_linedata_t;
+
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define GETDWFIELD(s,f) ((uint32_t)((s)->f##0) | ((uint32_t)((s)->f##1) << 8) | \
+ ((uint32_t)((s)->f##2) << 16) | ((uint32_t)((s)->f##3) << 24))
+#define PUTDWFIELD(s,f,v) (s)->f##0 = (v & 0xFF); \
+ (s)->f##1 = ((v)>>8 & 0xFF); \
+ (s)->f##2 = ((v)>>16 & 0xFF); \
+ (s)->f##3 = ((v)>>24 & 0xFF);
+
+
+
+/* *********************************************************************
+ * Forward Definitions
+ ********************************************************************* */
+
+static int usbserial_attach(usbdev_t *dev,usb_driver_t *drv);
+static int usbserial_detach(usbdev_t *dev);
+
+#ifdef _CFE_
+static void usb_uart_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+static int usb_uart_open(cfe_devctx_t *ctx);
+static int usb_uart_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int usb_uart_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int usb_uart_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int usb_uart_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int usb_uart_close(cfe_devctx_t *ctx);
+
+const static cfe_devdisp_t usb_uart_dispatch = {
+ usb_uart_open,
+ usb_uart_read,
+ usb_uart_inpstat,
+ usb_uart_write,
+ usb_uart_ioctl,
+ usb_uart_close,
+ NULL,
+ NULL
+};
+
+const cfe_driver_t usb_uart = {
+ "USB UART",
+ "uart",
+ CFE_DEV_SERIAL,
+ &usb_uart_dispatch,
+ usb_uart_probe
+};
+
+typedef struct usb_uart_s {
+ int uart_unit;
+ int uart_speed;
+ int uart_flowcontrol;
+} usb_uart_t;
+
+#define USBUART_MAXUNITS 4
+static usbdev_t *usbuart_units[USBUART_MAXUNITS];
+#endif
+
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef struct usbserial_softc_s {
+ int user_inpipe;
+ int user_outpipe;
+ int user_outmps;
+ int user_intpipe;
+ uint8_t user_inbuf[USER_FIFOSIZE];
+ int user_inbuf_in;
+ int user_inbuf_out;
+ uint8_t *user_devinbuf;
+ int user_devinbufsize;
+ int user_unit;
+ uint8_t *user_intbuf;
+ usbser_linedata_t user_linedata;
+} usbserial_softc_t;
+
+usb_driver_t usbserial_driver = {
+ "USB Serial Port",
+ usbserial_attach,
+ usbserial_detach
+};
+
+usbdev_t *usbserial_dev = NULL;
+
+
+#if 0
+/* *********************************************************************
+ * usbserial_get_linedata(dev,linedata)
+ *
+ * Request line data from the device.
+ *
+ * Input parameters:
+ * dev - USB device
+ * linedata - pointer to structure
+ *
+ * Return value:
+ * # of bytes returned
+ * <0 if error
+ ********************************************************************* */
+
+static int usbserial_get_linedata(usbdev_t *dev,usbser_linedata_t *ldata)
+{
+ uint8_t *respbuf;
+ int res;
+
+ respbuf = KMALLOC(32,0);
+
+ res = usb_std_request(dev,0xA1,0x21,0,0,respbuf,sizeof(usbser_linedata_t));
+
+ KFREE(respbuf);
+
+ if ((res >= 0) && ldata) memcpy(ldata,respbuf,sizeof(usbser_linedata_t));
+
+ return res;
+}
+#endif
+
+/* *********************************************************************
+ * usbserial_set_linedata(dev,linedata)
+ *
+ * Set line data to the device.
+ *
+ * Input parameters:
+ * dev - USB device
+ * linedata - pointer to structure
+ *
+ * Return value:
+ * # of bytes returned
+ * <0 if error
+ ********************************************************************* */
+
+static int usbserial_set_linedata(usbdev_t *dev,usbser_linedata_t *ldata)
+{
+ int res;
+
+ /*
+ * Send request to device.
+ */
+
+ res = usb_std_request(dev,0x21,0x20,0,0,(uint8_t *) ldata,sizeof(usbser_linedata_t));
+
+ return res;
+}
+
+#if 0
+/* *********************************************************************
+ * usbserial_song_and_dance(usbdev_t *dev)
+ *
+ * Magic incantations from using the CATC on this device.
+ *
+ * Input parameters:
+ * dev
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int usbserial_song_and_dance(usbdev_t *dev)
+{
+ int res;
+ char databuf[1];
+
+ res = usb_std_request(dev,0xc0,0x01,0x8484,0,databuf,1); /* READ */
+
+ res = usb_std_request(dev,0x40,0x01,0x0404,0,NULL,0); /* WRITE */
+
+ res = usb_std_request(dev,0xc0,0x01,0x8484,0,databuf,1); /* READ */
+ res = usb_std_request(dev,0xc0,0x01,0x8383,0,databuf,1); /* READ */
+ res = usb_std_request(dev,0xc0,0x01,0x8484,0,databuf,1); /* READ */
+
+ res = usb_std_request(dev,0x40,0x01,0x0404,1,NULL,0); /* WRITE */
+
+ res = usb_std_request(dev,0xc0,0x01,0x8484,0,databuf,1); /* READ */
+ res = usb_std_request(dev,0xc0,0x01,0x8383,0,databuf,1); /* READ */
+
+ res = usb_std_request(dev,0x40,0x01,0x0,1, NULL,0); /* WRITE */
+ res = usb_std_request(dev,0x40,0x01,0x1,0xC0,NULL,0); /* WRITE */
+ res = usb_std_request(dev,0x40,0x01,0x2,4, NULL,0); /* WRITE */
+
+ return 0;
+}
+#endif
+
+/* *********************************************************************
+ * usbserial_tx_data(dev,buffer,len)
+ *
+ * Synchronously transmit data via the USB.
+ *
+ * Input parameters:
+ * dev - device pointer
+ * buffer,len - data we want to send
+ *
+ * Return value:
+ * number of bytes sent.
+ ********************************************************************* */
+
+static int usbserial_tx_data(usbdev_t *dev,uint8_t *buffer,int len)
+{
+ uint8_t *bptr;
+ usbreq_t *ur;
+ usbserial_softc_t *softc = (dev->ud_private);
+ int res;
+
+ bptr = KMALLOC(len,0);
+
+ memcpy(bptr,buffer,len);
+
+ ur = usb_make_request(dev,softc->user_outpipe,bptr,len,UR_FLAG_OUT);
+ res = usb_sync_request(ur);
+
+// printf("Data sent, status=%d, xferred=%d\n",res,ur->ur_xferred);
+
+ res = ur->ur_xferred;
+
+ usb_free_request(ur);
+
+ KFREE(bptr);
+
+ return res;
+}
+
+/* *********************************************************************
+ * usbserial_int_callback(ur)
+ *
+ * Callback routine for the interrupt request, for devices
+ * that have an interrupt pipe. We ignore this.
+ *
+ * Input parameters:
+ * ur - usb request
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static int usbserial_int_callback(usbreq_t *ur)
+{
+// int idx;
+
+ /*
+ * Check to see if the request was cancelled by someone
+ * deleting our endpoint.
+ */
+
+ if (ur->ur_status == 0xFF) {
+ usb_free_request(ur);
+ return 0;
+ }
+
+// printf("serial int msg: ");
+// for (idx = 0; idx < ur->ur_xferred; idx++) printf("%02X ",ur->ur_buffer[idx]);
+// printf("\n");
+
+ usb_queue_request(ur);
+
+ return 0;
+
+}
+
+
+/* *********************************************************************
+ * usbserial_rx_callback(ur)
+ *
+ * Callback routine for the regular data pipe.
+ *
+ * Input parameters:
+ * ur - usb request
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static int usbserial_rx_callback(usbreq_t *ur)
+{
+ int idx;
+ int iptr;
+ usbserial_softc_t *user = (ur->ur_dev->ud_private);
+
+ /*
+ * Check to see if the request was cancelled by someone
+ * deleting our endpoint.
+ */
+
+ if (ur->ur_status == 0xFF) {
+ usb_free_request(ur);
+ return 0;
+ }
+
+ /*
+ * Add characters to the receive fifo
+ */
+
+ for (idx = 0; idx < ur->ur_xferred; idx++) {
+ iptr = (user->user_inbuf_in + 1) & (USER_FIFOSIZE-1);
+ if (iptr == user->user_inbuf_out) break; /* overflow */
+ user->user_inbuf[user->user_inbuf_in] = ur->ur_buffer[idx];
+ user->user_inbuf_in = iptr;
+ }
+
+ /*
+ * Requeue the request
+ */
+
+ usb_queue_request(ur);
+
+ return 0;
+
+}
+
+
+/* *********************************************************************
+ * usbserial_attach(dev,drv)
+ *
+ * This routine is called when the bus scan stuff finds a mass-storage
+ * device. We finish up the initialization by configuring the
+ * device and allocating our softc here.
+ *
+ * Input parameters:
+ * dev - usb device, in the "addressed" state.
+ * drv - the driver table entry that matched
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int usbserial_attach(usbdev_t *dev,usb_driver_t *drv)
+{
+ usb_config_descr_t *cfgdscr = dev->ud_cfgdescr;
+ usb_endpoint_descr_t *epdscr;
+ usb_endpoint_descr_t *indscr = NULL;
+ usb_endpoint_descr_t *outdscr = NULL;
+ usb_endpoint_descr_t *intdscr = NULL;
+ usb_interface_descr_t *ifdscr;
+ usbser_linedata_t *ldata;
+ usbserial_softc_t *softc;
+ usbreq_t *ur;
+ int idx;
+
+ dev->ud_drv = drv;
+
+ softc = KMALLOC(sizeof(usbserial_softc_t),0);
+ memset(softc,0,sizeof(usbserial_softc_t));
+ dev->ud_private = softc;
+
+ ifdscr = usb_find_cfg_descr(dev,USB_INTERFACE_DESCRIPTOR_TYPE,0);
+ if (ifdscr == NULL) {
+ printf("Could not get interface descriptor\n");
+ return -1;
+ }
+
+ for (idx = 0; idx < ifdscr->bNumEndpoints; idx++) {
+ epdscr = usb_find_cfg_descr(dev,USB_ENDPOINT_DESCRIPTOR_TYPE,idx);
+
+ if ((epdscr->bmAttributes & USB_ENDPOINT_TYPE_MASK) ==
+ USB_ENDPOINT_TYPE_INTERRUPT) {
+ intdscr = epdscr;
+ }
+ else if (USB_ENDPOINT_DIR_OUT(epdscr->bEndpointAddress)) {
+ outdscr = epdscr;
+ }
+ else {
+ indscr = epdscr;
+ }
+ }
+
+
+ if (!indscr || !outdscr) {
+ printf("IN or OUT endpoint descriptors are missing\n");
+ /*
+ * Could not get descriptors, something is very wrong.
+ * Leave device addressed but not configured.
+ */
+ return 0;
+ }
+
+ /*
+ * Choose the standard configuration.
+ */
+
+ usb_set_configuration(dev,cfgdscr->bConfigurationValue);
+
+ /*
+ * Open the pipes.
+ */
+
+ softc->user_inpipe = usb_open_pipe(dev,indscr);
+ softc->user_devinbufsize = GETUSBFIELD(indscr,wMaxPacketSize);
+ softc->user_devinbuf = KMALLOC(softc->user_devinbufsize,0);
+ softc->user_outpipe = usb_open_pipe(dev,outdscr);
+ softc->user_outmps = GETUSBFIELD(outdscr,wMaxPacketSize);
+ if (intdscr) {
+ softc->user_intpipe = usb_open_pipe(dev,intdscr);
+ }
+ else {
+ softc->user_intpipe = -1;
+ }
+
+ ur = usb_make_request(dev,softc->user_inpipe,softc->user_devinbuf,
+ softc->user_devinbufsize,
+ UR_FLAG_IN | UR_FLAG_SHORTOK);
+ ur->ur_callback = usbserial_rx_callback;
+ usb_queue_request(ur);
+
+
+ if (softc->user_intpipe) {
+ softc->user_intbuf = KMALLOC(32,0);
+ ur = usb_make_request(dev,softc->user_intpipe,softc->user_intbuf,
+ GETUSBFIELD(intdscr,wMaxPacketSize),
+ UR_FLAG_IN | UR_FLAG_SHORTOK);
+ ur->ur_callback = usbserial_int_callback;
+ usb_queue_request(ur);
+ }
+
+#ifdef _CFE_
+ softc->user_unit = -1;
+ for (idx = 0; idx < USBUART_MAXUNITS; idx++) {
+ if (usbuart_units[idx] == NULL) {
+ softc->user_unit = idx;
+ usbuart_units[idx] = dev;
+ break;
+ }
+ }
+
+ console_log("USBSERIAL: Unit %d connected",softc->user_unit);
+#endif
+
+// usbserial_song_and_dance(dev);
+
+ ldata = &(softc->user_linedata);
+ PUTDWFIELD(ldata,dLineDataBaud,115200);
+ ldata->bLineDataStopBits = 0;
+ ldata->bLineDataParity = 2;
+ ldata->bLineDataBits = 8;
+
+ usbserial_set_linedata(dev,ldata);
+// usbserial_get_linedata(dev,NULL);
+
+ usbserial_dev = dev;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * usbserial_detach(dev)
+ *
+ * This routine is called when the bus scanner notices that
+ * this device has been removed from the system. We should
+ * do any cleanup that is required. The pending requests
+ * will be cancelled automagically.
+ *
+ * Input parameters:
+ * dev - usb device
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int usbserial_detach(usbdev_t *dev)
+{
+ usbserial_softc_t *softc;
+
+ softc = dev->ud_private;
+
+
+#ifdef _CFE_
+ console_log("USBSERIAL: USB unit %d disconnected",softc->user_unit);
+ if (softc->user_unit >= 0) usbuart_units[softc->user_unit] = NULL;
+#endif
+
+ if (softc) {
+ if (softc->user_devinbuf) KFREE(softc->user_devinbuf);
+ if (softc->user_intbuf) KFREE(softc->user_intbuf);
+ KFREE(softc);
+ }
+
+ return 0;
+}
+
+
+
+#ifdef _CFE_
+
+
+
+static void usb_uart_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ usb_uart_t *softc;
+ char descr[80];
+
+ softc = (usb_uart_t *) KMALLOC(sizeof(usb_uart_t),0);
+
+ memset(softc,0,sizeof(usb_uart_t));
+
+ softc->uart_unit = (int)probe_a;
+
+ xsprintf(descr,"USB UART unit %d",(int)probe_a);
+
+ cfe_attach(drv,softc,NULL,descr);
+}
+
+
+static int usb_uart_open(cfe_devctx_t *ctx)
+{
+// usb_uart_t *softc = ctx->dev_softc;
+// int baudrate = CFG_SERIAL_BAUD_RATE;
+// usbdev_t *dev = usbuart_units[softc->uart_unit];
+
+ /*
+ * XXX call the uart setup here
+ */
+
+ return 0;
+}
+
+static int usb_uart_read(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ usb_uart_t *softc = ctx->dev_softc;
+ usbdev_t *dev = usbuart_units[softc->uart_unit];
+ usbserial_softc_t *user = dev->ud_private;
+ unsigned char *bptr;
+ int blen;
+
+ if (!dev) return 0;
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+
+ while ((blen > 0) && (user->user_inbuf_out != user->user_inbuf_in)) {
+ *bptr++ = user->user_inbuf[user->user_inbuf_out];
+ user->user_inbuf_out = (user->user_inbuf_out + 1) & (USER_FIFOSIZE-1);
+ blen--;
+ }
+
+ buffer->buf_retlen = buffer->buf_length - blen;
+ return 0;
+}
+
+static int usb_uart_inpstat(cfe_devctx_t *ctx, iocb_inpstat_t *inpstat)
+{
+ usb_uart_t *softc = ctx->dev_softc;
+ usbdev_t *dev = usbuart_units[softc->uart_unit];
+ usbserial_softc_t *user = dev->ud_private;
+
+ inpstat->inp_status = 0;
+
+ if (!dev) return 0;
+
+ inpstat->inp_status = (user->user_inbuf_in != user->user_inbuf_out);
+
+ return 0;
+}
+
+static int usb_uart_write(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ usb_uart_t *softc = ctx->dev_softc;
+ unsigned char *bptr;
+ int blen;
+ usbdev_t *dev = usbuart_units[softc->uart_unit];
+ usbserial_softc_t *user = dev->ud_private;
+
+ bptr = buffer->buf_ptr;
+ blen = buffer->buf_length;
+
+ if (!dev) {
+ buffer->buf_retlen = blen;
+ return 0;
+ }
+
+ if (blen > user->user_outmps) blen = user->user_outmps;
+
+ usbserial_tx_data(dev,bptr,blen);
+
+ buffer->buf_retlen = blen;
+ return 0;
+}
+
+static int usb_uart_ioctl(cfe_devctx_t *ctx, iocb_buffer_t *buffer)
+{
+ usb_uart_t *softc = ctx->dev_softc;
+ usbdev_t *dev = usbuart_units[softc->uart_unit];
+// usbserial_softc_t *user = dev->ud_private;
+
+ if (!dev) return -1;
+
+ unsigned int *info = (unsigned int *) buffer->buf_ptr;
+
+ switch ((int)buffer->buf_ioctlcmd) {
+ case IOCTL_SERIAL_GETSPEED:
+ *info = softc->uart_speed;
+ break;
+ case IOCTL_SERIAL_SETSPEED:
+ softc->uart_speed = *info;
+ /* NYI */
+ break;
+ case IOCTL_SERIAL_GETFLOW:
+ *info = softc->uart_flowcontrol;
+ break;
+ case IOCTL_SERIAL_SETFLOW:
+ softc->uart_flowcontrol = *info;
+ /* NYI */
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int usb_uart_close(cfe_devctx_t *ctx)
+{
+// usb_uart_t *softc = ctx->dev_softc;
+
+ return 0;
+}
+
+
+
+#endif
+
diff --git a/cfe/cfe/vendor/Makefile b/cfe/cfe/vendor/Makefile
new file mode 100644
index 0000000..a9fb42c
--- /dev/null
+++ b/cfe/cfe/vendor/Makefile
@@ -0,0 +1,2 @@
+
+ALLOBJS += cfe_vendor_xreq.o cfe_vendor_iocb_dispatch.o cfe_vendor_cmds.o
diff --git a/cfe/cfe/vendor/cfe_vendor_cmds.c b/cfe/cfe/vendor/cfe_vendor_cmds.c
new file mode 100644
index 0000000..34a159d
--- /dev/null
+++ b/cfe/cfe/vendor/cfe_vendor_cmds.c
@@ -0,0 +1,27 @@
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_devfuncs.h"
+#include "cfe_timer.h"
+
+#include "cfe_error.h"
+
+#include "ui_command.h"
+#include "cfe.h"
+
+#include "bsp_config.h"
+
+int ui_init_vendorcmds(void);
+
+
+int ui_init_vendorcmds(void)
+{
+ return 0;
+}
diff --git a/cfe/cfe/vendor/cfe_vendor_iocb.h b/cfe/cfe/vendor/cfe_vendor_iocb.h
new file mode 100644
index 0000000..33581cb
--- /dev/null
+++ b/cfe/cfe/vendor/cfe_vendor_iocb.h
@@ -0,0 +1,87 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * IOCB definitions File: cfe_iocb.h
+ *
+ * This module describes CFE's IOCB structure, the main
+ * data structure used to communicate API requests with CFE.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifndef _CFE_VENDOR_IOCB_H
+#define _CFE_VENDOR_IOCB_H
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define CFE_CMD_VENDOR_SAMPLE (CFE_CMD_VENDOR_USE+0)
+
+#define CFE_CMD_VENDOR_MAX (CFE_CMD_VENDOR_USE+1)
+
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+/*
+ * Vendor note: The fields in this structure leading up to the
+ * union *must* match the ones in cfe_iocb.h
+ *
+ * You can declare your own parameter list members here, since
+ * only your functions will be using them.
+ */
+
+
+typedef struct cfe_vendor_iocb_s {
+ cfe_uint_t iocb_fcode; /* IOCB function code */
+ cfe_int_t iocb_status; /* return status */
+ cfe_int_t iocb_handle; /* file/device handle */
+ cfe_uint_t iocb_flags; /* flags for this IOCB */
+ cfe_uint_t iocb_psize; /* size of parameter list */
+ union {
+ /* add/replace parameter list here */
+ iocb_buffer_t iocb_buffer; /* buffer parameters */
+ } plist;
+} cfe_vendor_iocb_t;
+
+
+#endif
+
diff --git a/cfe/cfe/vendor/cfe_vendor_iocb_dispatch.c b/cfe/cfe/vendor/cfe_vendor_iocb_dispatch.c
new file mode 100644
index 0000000..fb00c03
--- /dev/null
+++ b/cfe/cfe/vendor/cfe_vendor_iocb_dispatch.c
@@ -0,0 +1,179 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * IOCB dispatcher File: cfe_vendor_iocb_dispatch.c
+ *
+ * This routine is the main API dispatch for CFE. User API
+ * calls, via the ROM entry point, get dispatched to routines
+ * in this module.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "cfe_iocb.h"
+#include "cfe_vendor_iocb.h"
+#include "cfe_error.h"
+#include "cfe_device.h"
+#include "cfe_timer.h"
+#include "cfe_mem.h"
+#include "cfe_fileops.h"
+#include "cfe_boot.h"
+#include "env_subr.h"
+#include "cfe.h"
+#include "cfe_console.h"
+#include "bsp_config.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define HV 1 /* handle valid */
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+extern cfe_devctx_t *cfe_handle_table[CFE_MAX_HANDLE];
+
+/* *********************************************************************
+ * Prototypes
+ ********************************************************************* */
+
+int cfe_vendor_iocb_dispatch(cfe_iocb_t *iocb);
+
+/* *********************************************************************
+ * Dispatch table
+ ********************************************************************* */
+
+struct cfe_vendor_cmd_dispatch_s {
+ int plistsize;
+ int flags;
+ int (*func)(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+};
+
+
+static int cfe_cmd_vendor_sample(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
+
+const static struct cfe_vendor_cmd_dispatch_s
+ cfe_vendor_cmd_dispatch_table[CFE_CMD_VENDOR_MAX - CFE_CMD_VENDOR_USE] = {
+ {sizeof(iocb_buffer_t), 0, cfe_cmd_vendor_sample}, /* 0 : CFE_CMD_VENDOR_SAMPLE */
+};
+
+/* *********************************************************************
+ * IOCB dispatch routines
+ ********************************************************************* */
+
+
+int cfe_vendor_iocb_dispatch(cfe_iocb_t *iocb)
+{
+ const struct cfe_vendor_cmd_dispatch_s *disp;
+ int res;
+ cfe_devctx_t *ctx;
+
+ /*
+ * Check for commands codes out of range
+ */
+
+ if ((iocb->iocb_fcode < CFE_CMD_VENDOR_USE) ||
+ (iocb->iocb_fcode >= CFE_CMD_VENDOR_MAX)) {
+ iocb->iocb_status = CFE_ERR_INV_COMMAND;
+ return iocb->iocb_status;
+ }
+
+ /*
+ * Check for command codes in range but invalid
+ */
+
+ disp = &cfe_vendor_cmd_dispatch_table[iocb->iocb_fcode - CFE_CMD_VENDOR_USE];
+
+ if (disp->plistsize < 0) {
+ iocb->iocb_status = CFE_ERR_INV_COMMAND;
+ return iocb->iocb_status;
+ }
+
+ /*
+ * Check for invalid parameter list size
+ */
+
+ if (disp->plistsize != iocb->iocb_psize) {
+ iocb->iocb_status = CFE_ERR_INV_PARAM;
+ return iocb->iocb_status;
+ }
+
+ /*
+ * Determine handle
+ */
+
+ ctx = NULL;
+ if (disp->flags & HV) {
+ if ((iocb->iocb_handle >= CFE_MAX_HANDLE) ||
+ (iocb->iocb_handle < 0) ||
+ (cfe_handle_table[iocb->iocb_handle] == NULL)){
+ iocb->iocb_status = CFE_ERR_INV_PARAM;
+ return iocb->iocb_status;
+ }
+ ctx = cfe_handle_table[iocb->iocb_handle];
+ }
+
+ /*
+ * Dispatch to handler routine
+ */
+
+ res = (*disp->func)(ctx,iocb);
+
+ iocb->iocb_status = res;
+ return res;
+}
+
+
+
+/* *********************************************************************
+ * Implementation routines for each IOCB function
+ ********************************************************************* */
+
+static int cfe_cmd_vendor_sample(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
+{
+ return CFE_OK;
+}
diff --git a/cfe/cfe/vendor/cfe_vendor_xiocb.h b/cfe/cfe/vendor/cfe_vendor_xiocb.h
new file mode 100644
index 0000000..950ebcf
--- /dev/null
+++ b/cfe/cfe/vendor/cfe_vendor_xiocb.h
@@ -0,0 +1,91 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * IOCB definitions File: cfe_iocb.h
+ *
+ * This module describes CFE's IOCB structure, the main
+ * data structure used to communicate API requests with CFE.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#ifndef _CFE_VENDOR_XIOCB_H
+#define _CFE_VENDOR_XIOCB_H
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define CFE_CMD_VENDOR_SAMPLE (CFE_CMD_VENDOR_USE+0)
+
+#define CFE_CMD_VENDOR_MAX (CFE_CMD_VENDOR_USE+1)
+
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+/*
+ * Vendor note: The fields in this structure leading up to the
+ * union *must* match the ones in cfe_xiocb.h
+ *
+ * You can declare your own parameter list members here, since
+ * only your functions will be using them.
+ *
+ * You can also use some of the parameter list members in
+ * the regular xiocb.h if they are appropriate for your
+ * extended function calls.
+ */
+
+
+typedef struct cfe_vendor_xiocb_s {
+ cfe_xuint_t xiocb_fcode; /* IOCB function code */
+ cfe_xint_t xiocb_status; /* return status */
+ cfe_xint_t xiocb_handle; /* file/device handle */
+ cfe_xuint_t xiocb_flags; /* flags for this IOCB */
+ cfe_xuint_t xiocb_psize; /* size of parameter list */
+ union {
+ /* add/replace parameter list here */
+ xiocb_buffer_t xiocb_buffer; /* buffer parameters */
+ } plist;
+} cfe_vendor_xiocb_t;
+
+
+#endif
+
diff --git a/cfe/cfe/vendor/cfe_vendor_xreq.c b/cfe/cfe/vendor/cfe_vendor_xreq.c
new file mode 100644
index 0000000..f2ad541
--- /dev/null
+++ b/cfe/cfe/vendor/cfe_vendor_xreq.c
@@ -0,0 +1,222 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * IOCB dispatcher File: cfe_vendor_xreq.c
+ *
+ * This routine is the main API dispatch for CFE. User API
+ * calls, via the ROM entry point, get dispatched to routines
+ * in this module.
+ *
+ * This version of cfe_xreq is used for vendor extensions to
+ * CFE.
+ *
+ * This module looks similar to cfe_iocb_dispatch - it is different
+ * in that the data structure used, cfe_xiocb_t, uses fixed
+ * size field members (specifically, all 64-bits) no matter how
+ * the firmware is compiled. This ensures a consistent API
+ * interface on any implementation. When you call CFE
+ * from another program, the entry vector comes here first.
+ *
+ * Should the normal cfe_iocb interface change, this one should
+ * be kept the same for backward compatibility reasons.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "cfe_iocb.h"
+#include "cfe_vendor_iocb.h"
+#include "cfe_xiocb.h"
+#include "cfe_vendor_xiocb.h"
+#include "cfe_error.h"
+#include "cfe_device.h"
+#include "cfe_timer.h"
+#include "cfe_mem.h"
+#include "env_subr.h"
+#include "cfe.h"
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+/* enum values for various plist types */
+
+#define PLBUF 1 /* iocb_buffer_t */
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+struct cfe_vendor_xcmd_dispatch_s {
+ int xplistsize;
+ int iplistsize;
+ int plisttype;
+};
+
+
+/* *********************************************************************
+ * Command conversion table
+ * This table contains useful information for converting
+ * iocbs to xiocbs.
+ ********************************************************************* */
+
+const static struct cfe_vendor_xcmd_dispatch_s
+ cfe_vendor_xcmd_dispatch_table[CFE_CMD_VENDOR_MAX-CFE_CMD_VENDOR_USE] = {
+ {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 0 : CFE_CMD_VENDOR_SAMPLE */
+};
+
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+extern int cfe_vendor_iocb_dispatch(cfe_vendor_iocb_t *iocb);
+extern cfe_int_t cfe_vendor_doxreq(cfe_vendor_xiocb_t *xiocb);
+
+/* *********************************************************************
+ * cfe_vendor_doxreq(xiocb)
+ *
+ * Process an xiocb request. This routine converts an xiocb
+ * into an iocb, calls the IOCB dispatcher, converts the results
+ * back into the xiocb, and returns.
+ *
+ * Input parameters:
+ * xiocb - pointer to user xiocb
+ *
+ * Return value:
+ * command status, <0 if error occured
+ ********************************************************************* */
+
+cfe_int_t cfe_vendor_doxreq(cfe_vendor_xiocb_t *xiocb)
+{
+ const struct cfe_vendor_xcmd_dispatch_s *disp;
+ cfe_vendor_iocb_t iiocb;
+ cfe_int_t res;
+
+ /*
+ * Check for commands codes out of range
+ */
+
+ if ((xiocb->xiocb_fcode < CFE_CMD_VENDOR_USE) ||
+ (xiocb->xiocb_fcode >= CFE_CMD_VENDOR_MAX)) {
+ xiocb->xiocb_status = CFE_ERR_INV_COMMAND;
+ return xiocb->xiocb_status;
+ }
+
+ /*
+ * Check for command codes in range but invalid
+ */
+
+ disp = &cfe_vendor_xcmd_dispatch_table[xiocb->xiocb_fcode - CFE_CMD_VENDOR_USE];
+
+ if (disp->xplistsize < 0) {
+ xiocb->xiocb_status = CFE_ERR_INV_COMMAND;
+ return xiocb->xiocb_status;
+ }
+
+ /*
+ * Check for invalid parameter list size
+ */
+
+ if (disp->xplistsize != xiocb->xiocb_psize) {
+ xiocb->xiocb_status = CFE_ERR_INV_PARAM;
+ return xiocb->xiocb_status;
+ }
+
+ /*
+ * Okay, copy parameters into the internal IOCB.
+ * First, the fixed header.
+ */
+
+ iiocb.iocb_fcode = (unsigned int) xiocb->xiocb_fcode;
+ iiocb.iocb_status = (int) xiocb->xiocb_status;
+ iiocb.iocb_handle = (int) xiocb->xiocb_handle;
+ iiocb.iocb_flags = (unsigned int) xiocb->xiocb_flags;
+ iiocb.iocb_psize = (unsigned int) disp->iplistsize;
+
+ /*
+ * Now the parameter list
+ */
+
+ switch (disp->plisttype) {
+ case PLBUF:
+ iiocb.plist.iocb_buffer.buf_offset = (cfe_offset_t) xiocb->plist.xiocb_buffer.buf_offset;
+ iiocb.plist.iocb_buffer.buf_ptr = (unsigned char *) (uintptr_t) xiocb->plist.xiocb_buffer.buf_ptr;
+ iiocb.plist.iocb_buffer.buf_length = (unsigned int) xiocb->plist.xiocb_buffer.buf_length;
+ iiocb.plist.iocb_buffer.buf_retlen = (unsigned int) xiocb->plist.xiocb_buffer.buf_retlen;
+ iiocb.plist.iocb_buffer.buf_ioctlcmd = (unsigned int) xiocb->plist.xiocb_buffer.buf_ioctlcmd;
+ break;
+ }
+
+ /*
+ * Do the internal function dispatch
+ */
+
+ res = (cfe_int_t) cfe_vendor_iocb_dispatch(&iiocb);
+
+ /*
+ * Now convert the parameter list members back
+ */
+
+ switch (disp->plisttype) {
+ case PLBUF:
+ xiocb->plist.xiocb_buffer.buf_offset = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_offset;
+ xiocb->plist.xiocb_buffer.buf_ptr = (cfe_xptr_t) (uintptr_t) iiocb.plist.iocb_buffer.buf_ptr;
+ xiocb->plist.xiocb_buffer.buf_length = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_length;
+ xiocb->plist.xiocb_buffer.buf_retlen = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_retlen;
+ xiocb->plist.xiocb_buffer.buf_ioctlcmd = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_ioctlcmd;
+ break;
+ }
+
+ /*
+ * And the fixed header
+ */
+
+ xiocb->xiocb_status = (cfe_int_t) iiocb.iocb_status;
+ xiocb->xiocb_handle = (cfe_int_t) iiocb.iocb_handle;
+ xiocb->xiocb_flags = (cfe_uint_t) iiocb.iocb_flags;
+
+ return xiocb->xiocb_status;
+}
diff --git a/cfe/cfe/verif/Makefile b/cfe/cfe/verif/Makefile
new file mode 100644
index 0000000..939b494
--- /dev/null
+++ b/cfe/cfe/verif/Makefile
@@ -0,0 +1,7 @@
+
+#
+# Object files needed by VAPI
+#
+
+CFLAGS += -DCFG_VAPI=1
+ALLOBJS += vapi.o vapisubr.o vapitest.o ui_vapi.o
diff --git a/cfe/cfe/verif/readme.txt b/cfe/cfe/verif/readme.txt
new file mode 100644
index 0000000..4a35dee
--- /dev/null
+++ b/cfe/cfe/verif/readme.txt
@@ -0,0 +1,342 @@
+CFE Diagnostic Entry Points
+---------------------------
+
+---------------------------------------------------------------------------
+
+The CFE diagnostic entry points are used when running verification
+programs under the control of the firmware. They are fixed (constant)
+addresses and have register-based calling sequences. These entry
+points are designed to be as minimal as possible so that as much of the
+verification code as possible can be reused.
+
+You can call the KSEG0 or KSEG1 version of the routine. It is
+recommended that you call the cached version from cached code and
+vice versa.
+
+The firmware will reserve the top megabyte of memory for itself. The
+diagnostic must not touch this memory.
+
+The firmware will be compiled to *NOT* use relocatable data and
+code segments.
+
+The firmware will need one general register that it is allowed to
+trash without saving - I'll be using this to generate the pointer to
+the save area.
+
+The diagnostics can generate records in a log buffer. This buffer
+is allocated in the diagnostic's memory space but is filled in
+by the firmware through the diagnostic entry points. At the end
+of the diagnostic run, user commands in the firmware may be used
+to look through accumulated log records.
+
+If you mess with the caches or with the console device, the
+VAPI functions that print messages to the console may not work.
+
+Log records follow this format:
+
+ +0 SIGNATURE, FORMAT, and ID-CODE
+ +8 Number of 64-bit words in 'Log Data' field.
+ Upper 32 bits are CP0 count register
+ +16 Return address of routine generating this record
+ +24 Log Data
+
+The "Log Record size" field is the number of bytes in the "log data"
+field. No log data would use a value of zero.
+
+The bytes in the SIGNATURE word are broken down as follows:
+
+ S1 S2 P1 F1 I1 I2 I3 I4
+ CF E1 pp xx ii ii ii ii
+
+The "F1" byte is the format code; it describes the type
+of log record being generated.
+
+ 0x00 - General register and CP0 dump
+ 0x01 - SOC state dump
+ 0x02 - Generic log data (multiple of 8 bytes)
+ 0x03 - trace RAM
+ 0x04 - Diagnostic termination status (8 bytes)
+ 0x05 - Floating point registers
+
+The "P1" byte is the processor number, 0 or 1.
+
+The "I1" through "I4" bytes are supplied by the diagnostic
+and can take on any value. You can use these bytes to identify
+what part of the program generated this particular log record.
+
+For example, if the diagnostic logs a single value of
+0x0123_4567_89ab_cdef the log entry might look like:
+
+ 0xCCFF_EE02_0000_0001
+ 0x0001_3F22_0000_0008
+ 0xFFFF_FFFF_8000_0120
+ 0x0123_4567_89AB_CDEF
+
+
+RETURN TO FIRMWARE
+------------------
+
+Description:
+
+ Returns control to the firmware and displays the test status.
+ The status result is in register A0.
+
+ The firmware will store a "diagnostic termination status"
+ record in the log with the A0 register value. The ID code
+ will be zero for this record.
+
+ CFE's log scanning commands can be used to display log
+ records accumulated by the test.
+
+
+Routine address: 0xBFC00510 (KSEG1)
+ 0x9FC00510 (KSEG0)
+
+On entry: A0 ($4) Exit status (9=ok, nonzero=fail)
+On return: Does not return
+Registers used: All
+
+
+DUMP GENERAL REGISTERS
+----------------------
+
+Description:
+
+ This routine causes CFE to display a register dump on the console
+ port. It is assumed that the console hardware state has not been
+ altered by the diagnostic.
+
+ The format of the register dump is: TBD [XXX should it look like the
+ one that the functional simulator uses?]
+
+ The firmware needs one scratch register.
+
+
+Routine address: 0xBFC00520 (KSEG1)
+ 0x9FC00520 (KSEG0)
+
+On Entry: RA ($31) Return Address
+On Return: nothing
+Registers used: K0 ($26) Scratch register for CFE
+
+
+SET LOG BUFFER
+--------------
+
+Description:
+
+ This routine sets the address of the log buffer. This
+ call must be made once at the beginning of the diagnostic
+ or else the "SAVE" functions will be considered as
+ NOPs.
+
+ The buffer addresses must be 64-bit aligned.
+
+Routine address: 0xBFC00530 (KSEG1)
+ 0x9FC00530 (KSEG0)
+
+On Entry: RA ($31) Return Address
+ A0 ($4) Address of start of buffer
+ A1 ($5) Address of end of buffer
+On Return: Nothing
+Registers Used: K0 ($26) Scratch register for CFE
+
+
+
+LOG SINGLE VALUE
+----------------
+
+Description:
+
+ This routine saves a single 64-bit value in the log.
+
+
+Routine address: 0xBFC00540 (KSEG1)
+ 0x9FC00540 (KSEG0)
+
+On Entry: RA ($31) Return Address
+ A0 ($4) Low 32 bits are ID code for value
+ A1 ($5) Value to log
+On Return: Nothing
+Registers Used: K0 ($26) Scratch register for CFE
+
+
+
+LOG MEMORY DATA
+---------------
+
+Description:
+
+ This routine saves a block of memory in the log. The source
+ buffer must be 64-bit aligned.
+
+
+Routine address: 0xBFC00550 (KSEG1)
+ 0x9FC00550 (KSEG0)
+
+On Entry: RA ($31) Return Address
+ A0 ($4) Low 32 bits are ID code for values
+ A1 ($5) Address of buffer containing values
+ A2 ($6) Number of 64-bit words to store
+On Return: Nothing
+Registers Used: K0 ($26) Scratch register for CFE
+
+
+
+
+
+SAVE SOC STATE
+--------------
+
+Description:
+
+ This routine saves the SOC state in a user-supplied buffer.
+ The buffer must be large enough to accomodate the SOC state.
+ The SOC state will be written as records with the following
+ format:
+
+ uint64_t phys_address
+ uint64_t value
+ uint64_t phys_address
+ uint64_t value
+ ...
+ uint64_t phys_address
+ uint64_t value
+
+ The table of SOC registers to dump will be maintained by
+ the firmware.
+
+ The firmware needs one scratch register.
+
+Routine address: 0xBFC00570 (KSEG1)
+ 0x9FC00570 (KSEG0)
+
+On entry: A0 ($4) Low 32 bits are ID code for values
+ A1 ($5) Bitmask of agents to store in log
+On return: nothing
+Registers used: K0 ($26) Scratch register for CFE
+
+
+SAVE CPU REGISTERS
+------------------
+
+Description:
+
+ This routine saves the CPU general registers and certain CP0
+ registers in a user-supplied buffer.
+
+ This buffer must be large enough to accomodate the data
+ that will be saved. The registers will be written in
+ the following format:
+
+ uint64_t general_registers[32]
+ uint64_t C0_INX
+ uint64_t C0_RAND
+ uint64_t C0_TLBLO0
+ uint64_t C0_TLBLO1
+ uint64_t C0_CTEXT
+ uint64_t C0_PGMASK
+ uint64_t C0_WIRED
+ uint64_t C0_BADVADDR
+ uint64_t C0_COUNT
+ uint64_t C0_TLBHI
+ uint64_t C0_COMPARE
+ uint64_t C0_SR
+ uint64_t C0_CAUSE
+ uint64_t C0_EPC
+ uint64_t C0_PRID
+ uint64_t C0_CONFIG
+ uint64_t C0_LLADDR
+ uint64_t C0_WATCHLO
+ uint64_t C0_WATCHHI
+ uint64_t C0_XCTEXT
+ uint64_t C0_ECC
+ uint64_t C0_CACHEERR
+ uint64_t C0_TAGLO
+ uint64_t C0_TAGHI
+ uint64_t C0_ERREPC
+
+ The firmware needs one scratch register.
+
+Routine address: 0xBFC00580 (KSEG1)
+ 0x9FC00580 (KSEG0)
+
+On entry: RA ($31) Return address
+ A0 ($4) Low 32 bits are ID code for values
+On return: nothing
+Registers used: K0 ($26) Scratch register for CFE
+
+
+SAVE FPU REGISTERS
+------------------
+
+Description:
+
+ This routine saves the floating point and floating point
+ control registers. The registers will be written in
+ the following format:
+
+ uint64_t fp_registers[32]
+ uint64_t fp_fir
+ uint64_t fp_status
+ uint64_t fp_condition_codes
+ uint64_t fp_exceptions
+ uint64_t fp_enables
+
+ The firmware needs one scratch register.
+
+Routine address: 0xBFC005B0 (KSEG1)
+ 0x9FC005B0 (KSEG0)
+
+On entry: RA ($31) Return address
+ A0 ($4) Low 32 bits are ID code for values
+On return: nothing
+Registers used: K0 ($26) Scratch register for CFE
+
+
+DUMP STRING
+-----------
+
+Description:
+
+ This routine displays a zero-terminated ASCII text string on the
+ console port.
+
+ The firmware needs one scratch register.
+
+
+Routine address: 0xBFC00590 (KSEG1)
+ 0x9FC00590 (KSEG0)
+
+On entry: RA ($31) Return address
+ A0 ($4) Pointer to null-terminated string
+On return: nothing
+Registers used: K0 ($26) Scratch register for CFE
+
+
+
+SHOW LED MESSAGE
+----------------
+
+Description:
+
+ This routine writes four characters onto the SWARM board LEDs.
+ Writing to the LEDs is very fast compared to writing to the
+ console and can be useful for providing progress feedback
+ during a run.
+
+ The characters are packed into the low 4 bytes of register A0.
+ The string ABCD would be hex 0x0000_0000_4142_4344
+
+ The firmware needs one scratch register
+
+Routine address: 0xBFC005A0 (KSEG1)
+ 0x9FC005A0 (KSEG0)
+
+On entry: RA ($31) Return Address
+ A0 ($4) Four characters
+On return: nothing
+Registers used: K0 ($26) Scratch register for CFE
+
+------------------------------------------------------------------------
+
diff --git a/cfe/cfe/verif/ui_vapi.c b/cfe/cfe/verif/ui_vapi.c
new file mode 100644
index 0000000..4575322
--- /dev/null
+++ b/cfe/cfe/verif/ui_vapi.c
@@ -0,0 +1,300 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * VAPI commands File: ui_vapi.c
+ *
+ * User interface for the verification API
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "bsp_config.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "env_subr.h"
+#include "ui_command.h"
+#include "cfe.h"
+
+#if CFG_VAPI
+
+#include "vapi.h"
+
+int ui_init_vapicmds(void);
+
+extern void vapitest(void);
+
+extern void vapi_run(int);
+
+extern uint64_t vapi_logstart;
+extern uint64_t vapi_logend;
+extern uint64_t vapi_logptr;
+extern uint64_t vapi_status;
+
+int ui_cmd_vapirun(ui_cmdline_t *cmd,int argc,char *argv[]);
+int ui_cmd_vapitest(ui_cmdline_t *cmd,int argc,char *argv[]);
+int ui_cmd_vapishow(ui_cmdline_t *cmd,int argc,char *argv[]);
+int ui_cmd_vapidump(ui_cmdline_t *cmd,int argc,char *argv[]);
+int ui_cmd_vapistatus(ui_cmdline_t *cmd,int argc,char *argv[]);
+
+static char *rectypes[7] = {
+ "GPRS ",
+ "SOC ",
+ "DATA ",
+ "BUF ",
+ "TRC ",
+ "EXIT ",
+ "FPRS "
+};
+
+int ui_cmd_vapidump(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ uint64_t *ptr;
+ uint64_t *eptr;
+ int recnum = 0;
+
+ if (vapi_logptr == 0) {
+ xprintf("Diagnostic did not record any log records\n");
+ return -1;
+ }
+
+ ptr = (uint64_t *) (intptr_t) vapi_logstart;
+ eptr = (uint64_t *) (intptr_t) vapi_logptr;
+
+ xprintf("*** VAPI LOG START %s\n",
+#ifdef __MIPSEB
+ "big-endian"
+#else
+ "little-endian"
+#endif
+ );
+
+ while (ptr < eptr) {
+ xprintf("%6d %016llX %016llX %016llX %016llX\n",
+ recnum,
+ ptr[0],ptr[1],ptr[2],ptr[3]);
+ ptr += 4;
+ recnum++;
+ }
+
+ xprintf("*** VAPI LOG END\n");
+
+ return 0;
+
+
+}
+
+int ui_cmd_vapishow(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ uint64_t *ptr;
+ uint64_t *eptr;
+ uint32_t a,b;
+ uint32_t ts,len,fmt;
+ unsigned int idx;
+ int recnum = 0;
+
+ if (vapi_logptr == 0) {
+ xprintf("Diagnostic did not record any log records\n");
+ return -1;
+ }
+
+ ptr = (uint64_t *) (intptr_t) vapi_logstart;
+ eptr = (uint64_t *) (intptr_t) vapi_logptr;
+
+ while (ptr < eptr) {
+ a = (ptr[VAPI_IDX_SIGNATURE]) >> 32;
+ b = (ptr[VAPI_IDX_SIGNATURE]) & 0xFFFFFFFF;
+ if ((a & VAPI_SEAL_MASK) != VAPI_CFESEAL) {
+ xprintf("Incorrect record seal at %08X\n",ptr);
+ break;
+ }
+
+ fmt = (a & VAPI_FMT_MASK);
+
+ xprintf("%5d ID=%08X CPU%d %s RA=%08X ",
+ recnum,
+ b,
+ (a & VAPI_PRID_MASK) >> VAPI_PRNUM_SHIFT,
+ rectypes[fmt],
+ ptr[VAPI_IDX_RA]);
+
+ ts = (ptr[VAPI_IDX_SIZE]) >> 32;
+ len = ((ptr[VAPI_IDX_SIZE]) & 0xFFFFFFFF);
+
+ xprintf("TS=%08X ",ts);
+
+ switch (fmt) {
+ case VAPI_FMT_GPRS:
+ xprintf("Len=%d\n",len);
+ for (idx = 0; idx < len; idx += 2) {
+ xprintf(" %016llX %016llX\n",
+ ptr[VAPI_IDX_DATA+idx],
+ ptr[VAPI_IDX_DATA+idx+1]);
+ }
+ break;
+ case VAPI_FMT_SOC:
+ xprintf("Len=%d\n",len);
+ for (idx = 0; idx < len; idx += 2) {
+ xprintf(" Reg=%016llX Val=%016llX\n",
+ ptr[VAPI_IDX_DATA+idx],
+ ptr[VAPI_IDX_DATA+idx+1]);
+ }
+ break;
+ case VAPI_FMT_DATA:
+ xprintf("Data=%016llX\n",ptr[VAPI_IDX_DATA]);
+ break;
+ case VAPI_FMT_BUFFER:
+ xprintf("Addr=%08X\n",(intptr_t) ptr[VAPI_IDX_DATA]);
+ for (idx = 0; idx < len-1; idx += 2) {
+ xprintf(" %016llX %016llX\n",
+ ptr[VAPI_IDX_DATA+idx+1],
+ ptr[VAPI_IDX_DATA+idx+2]);
+ }
+ if (idx != (len-1)) {
+ xprintf(" %016llX\n",
+ ptr[VAPI_IDX_DATA+idx+1]);
+ }
+ break;
+ case VAPI_FMT_TRACE:
+ xprintf("\n");
+ break;
+ case VAPI_FMT_EXIT:
+ xprintf("Stat=%016llX\n",ptr[VAPI_IDX_DATA]);
+ break;
+ default:
+ xprintf("\n");
+ break;
+ }
+
+ ptr += 3 + len;
+ recnum++;
+ }
+
+ return 0;
+
+}
+
+int ui_cmd_vapitest(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+
+ vapitest();
+
+ xprintf("LogStart=%llX LogEnd=%llX LogPtr=%llX\n",
+ vapi_logstart,vapi_logend,vapi_logptr);
+
+ return 0;
+}
+
+int ui_cmd_vapistatus(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+
+ xprintf("VAPI Exit Status = <%016llX>\n", vapi_status);
+ return 0;
+}
+
+int ui_cmd_vapirun(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int mode; /* 0 = cached, 1 = uncached, 2 = mc mode */
+
+ mode = 0;
+ if (cmd_sw_isset(cmd,"-uncached")) mode = 1;
+ if (cmd_sw_isset(cmd,"-mc")) mode = 2;
+
+ vapi_run(mode);
+ return -1;
+}
+
+
+int ui_init_vapicmds(void)
+{
+ cmd_addcmd("vapi run",
+ ui_cmd_vapirun,
+ NULL,
+ "Run a program using the VAPI reset vector.",
+ "vapi run\n"
+ "Executes a previously loaded VAPI program by resetting the\n"
+ "CPUs and jumping directly to user code. The program\n"
+ "must be located at absolute address 0x8002_0000\n",
+ "-uncached;Start execution at 0xA002_0000 (KSEG1)|"
+ "-mc;Start execution at 0xBFD0_0000");
+
+ cmd_addcmd("vapi test",
+ ui_cmd_vapitest,
+ NULL,
+ "Test VAPI interface.",
+ "vapi test\n\n"
+ "Do some basic calls to the VAPI interface, then return to CFE\n\n",
+ "");
+
+ cmd_addcmd("vapi dump",
+ ui_cmd_vapidump,
+ NULL,
+ "Show VAPI log in an easily processed format.",
+ "vapi dump\n\n"
+ "Display the VAPI log in a format that is more easily postprocessed\n"
+ "by external programs.\n\n",
+ "");
+
+ cmd_addcmd("vapi show",
+ ui_cmd_vapishow,
+ NULL,
+ "Show VAPI log.\n",
+ "vapi show\n\n"
+ "Display the VAPI log in a human readable form (sort of)\n\n",
+ "");
+
+ cmd_addcmd("vapi status",
+ ui_cmd_vapistatus,
+ NULL,
+ "Print last VAPI exit status.\n",
+ "vapi status\n\n"
+ "Display the exit status of the last VAPI program that was run\n",
+ "");
+
+ return 0;
+}
+
+#endif
diff --git a/cfe/cfe/verif/vapi.S b/cfe/cfe/verif/vapi.S
new file mode 100644
index 0000000..a65fb6d
--- /dev/null
+++ b/cfe/cfe/verif/vapi.S
@@ -0,0 +1,1150 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Verification Test APIs File: vapi.S
+ *
+ * This module contains special low-level routines for use
+ * by verification programs.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "sbmips.h"
+#include "bsp_config.h"
+#include "mipsmacros.h"
+
+#if CFG_VAPI
+
+#if (CFG_EMBEDDED_PIC)
+#error "CFG_VAPI is not compatible with relocatable code"
+#endif
+
+#include "cfe_devfuncs.h"
+
+#include "sb1250_defs.h"
+#include "sb1250_regs.h"
+#include "sb1250_scd.h"
+
+#include "vapi.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define CALLKSEG1(x) \
+ la t0,x ; \
+ or t0,K1BASE ; \
+ jal t0
+
+#ifndef CFG_STACK_SIZE
+#define STACK_SIZE 8192
+#else
+#define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023)
+#endif
+
+#define REGIDX(x) ((x)*8)
+
+#define SAVE_RA REGIDX(0)
+#define SAVE_GP REGIDX(1)
+#define SAVE_AT REGIDX(2)
+#define SAVE_T0 REGIDX(3)
+#define SAVE_T1 REGIDX(4)
+#define SAVE_T2 REGIDX(5)
+#define SAVE_T3 REGIDX(6)
+#define SAVE_A0 REGIDX(7)
+#define SAVE_A1 REGIDX(8)
+#define SAVE_A2 REGIDX(9)
+
+#define SAVE_SIZE REGIDX(10)
+
+#define SAVETEMPS(x) \
+ .set noat ; \
+ la k0,x ; \
+ sd ra,SAVE_RA(k0) ; \
+ sd gp,SAVE_GP(k0) ; \
+ sd AT,SAVE_AT(k0) ; \
+ sd t0,SAVE_T0(k0) ; \
+ sd t1,SAVE_T1(k0) ; \
+ sd t2,SAVE_T2(k0) ; \
+ sd t3,SAVE_T3(k0) ; \
+ sd a0,SAVE_A0(k0) ; \
+ sd a1,SAVE_A1(k0) ; \
+ sd a2,SAVE_A2(k0) ; \
+ .set at ; \
+ la gp,_gp
+
+
+#define RESTORETEMPS(x) \
+ .set noat ; \
+ la k0,x ; \
+ ld ra,SAVE_RA(k0) ; \
+ ld gp,SAVE_GP(k0) ; \
+ ld AT,SAVE_AT(k0) ; \
+ ld t0,SAVE_T0(k0) ; \
+ ld t1,SAVE_T1(k0) ; \
+ ld t2,SAVE_T2(k0) ; \
+ ld t3,SAVE_T3(k0) ; \
+ ld a0,SAVE_A0(k0) ; \
+ ld a1,SAVE_A1(k0) ; \
+ ld a2,SAVE_A2(k0) ; \
+ .set at
+
+#define RECPTR t3
+
+#define CHECKPTR(label) \
+ ld RECPTR,vapi_logptr ; \
+ ld t0,vapi_logend ; \
+ beq RECPTR,zero,label ; \
+ bge RECPTR,t0,label
+
+#define SETRECTYPE(x,id) \
+ ld RECPTR,vapi_logptr ; \
+ li t2,(VAPI_CFESEAL | (x)) ; \
+ mfc0 t0,C0_PRID ; \
+ srl t0,t0,25 ; \
+ and t0,t0,7 ; \
+ sll t0,t0,VAPI_PRNUM_SHIFT ; \
+ or t2,t2,t0 ; \
+ dsll t2,t2,32 ; \
+ or t2,id ; \
+ sd t2,VAPI_REC_SIGNATURE(RECPTR) ; \
+ mfc0 t2,C0_COUNT ; \
+ dsll t2,t2,32 ; \
+ sd t2,VAPI_REC_SIZE(RECPTR) ; \
+ sd ra,VAPI_REC_RA(RECPTR)
+
+
+
+#define SETRECLEN_CONST(len) \
+ ld t2,VAPI_REC_SIZE(RECPTR) ; \
+ or t2,len ; \
+ sd t2,VAPI_REC_SIZE(RECPTR)
+
+#define SETRECLEN_REG(r) \
+ ld t2,VAPI_REC_SIZE(RECPTR) ; \
+ or t2,r ; \
+ sd t2,VAPI_REC_SIZE(RECPTR)
+
+
+/* *********************************************************************
+ * Data
+ ********************************************************************* */
+
+ .sdata
+
+ .globl vapi_logstart
+ .globl vapi_logend
+ .globl vapi_logptr
+ .globl vapi_status
+ .globl vapi_logover
+
+vapi_logstart: .dword 0
+vapi_logend: .dword 0
+vapi_logptr: .dword 0
+vapi_status: .dword -1
+vapi_logover: .dword 0
+
+ .extern mem_heapstart
+
+ .bss
+
+ .comm vapi_regsave,REGIDX(64)
+
+ .text
+
+ .globl vapi_socregs
+vapi_socregs:
+
+#ifdef _P5064_
+ .word 0, 0
+#else
+#include "sb1250_socregs.inc"
+#endif
+
+ .text
+
+ .extern cfe_warmstart
+
+ .set reorder
+
+
+/* *********************************************************************
+ * VAPI_KSEG0_SWITCH
+ *
+ * Hack the return address so we will come back in KSEG0
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(vapi_kseg0_switch)
+
+ and ra,(K0SIZE-1)
+ or ra,K0BASE
+ jr ra
+
+END(vapi_kseg0_switch)
+
+/* *********************************************************************
+ * VAPI_EXIT(status)
+ *
+ * Return from diagnostic to firmware
+ *
+ * Input parameters:
+ * a0 - exit status (0=ok, else error)
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+
+LEAF(vapi_exit)
+
+ move k1,a0
+
+
+/*
+ * Reinitialize the CPU and the caches
+ */
+
+ bal vapi_kseg1_switch
+ CALLKSEG1(sb1_cpu_init)
+/*
+ * Don't initialize the caches again. Some diags
+ * leave data in the caches and if we invalidate it
+ * now we won't be able to see what happened.
+ */
+/* CALLKSEG1(sb1250_l1cache_init) */
+/* CALLKSEG1(sb1250_l2cache_init) */
+
+#ifdef __long64
+/*
+ * Set back to 64-bit mode. Don't worry about the hazard
+ * here, it'll be eons before we need to use the KX space.
+ */
+ mfc0 t0,C0_SR
+ or t0,t0,M_SR_KX
+ mtc0 t0,C0_SR
+#endif
+
+ bal vapi_kseg0_switch
+
+ li a0,0x42424242 # 'BBBB'
+ jal board_setleds
+
+ move a0,k1
+
+ la gp,_gp
+ sd a0,vapi_status
+ LR sp,mem_heapstart
+ ADD sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8)
+
+/*
+ * Create a log record for the EXIT status.
+ */
+ ld t0,vapi_logptr
+ beq t0,zero,nolog
+
+ SETRECTYPE(VAPI_FMT_EXIT,0)
+ SETRECLEN_CONST(1)
+ sd a0,VAPI_REC_DATA(RECPTR)
+ add RECPTR,32
+ sd RECPTR,vapi_logptr
+nolog:
+ li a0,0x45454545 # 'EEEE'
+ jal board_setleds
+
+#if CFG_MULTI_CPUS
+
+ /*
+ * Restart the other CPU if it was left in RESET.
+ */
+
+ la t2,PHYS_TO_K1(A_SCD_SYSTEM_CFG)
+ ld t0,0(t2)
+ dli t1,M_SYS_CPU_RESET_1 # Reset mask
+ and t0,t1 # Test if CPU is in reset
+ beq t0,zero,1f # skip if not in reset
+
+ li a0,1 # Whack the CPU
+ jal altcpu_cmd_stop # and put it back in idle
+1:
+#endif
+
+ ld a0,vapi_status
+ j cfe_warmstart
+
+END(vapi_exit)
+
+
+
+/* *********************************************************************
+ * VAPI_DUMPGPRS()
+ *
+ * Dump the GPRs to the console
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * k0 - scratch register for CFE
+ ********************************************************************* */
+
+LEAF(vapi_dumpgprs)
+
+ .set noat
+ la k0,vapi_regsave
+ sd $0,REGIDX(0)(k0)
+ sd $1,REGIDX(1)(k0)
+ sd $2,REGIDX(2)(k0)
+ sd $3,REGIDX(3)(k0)
+ sd $4,REGIDX(4)(k0)
+ sd $5,REGIDX(5)(k0)
+ sd $6,REGIDX(6)(k0)
+ sd $7,REGIDX(7)(k0)
+ sd $8,REGIDX(8)(k0)
+ sd $9,REGIDX(9)(k0)
+ sd $10,REGIDX(10)(k0)
+ sd $11,REGIDX(11)(k0)
+ sd $12,REGIDX(12)(k0)
+ sd $13,REGIDX(13)(k0)
+ sd $14,REGIDX(14)(k0)
+ sd $15,REGIDX(15)(k0)
+ sd $16,REGIDX(16)(k0)
+ sd $17,REGIDX(17)(k0)
+ sd $18,REGIDX(18)(k0)
+ sd $19,REGIDX(19)(k0)
+ sd $20,REGIDX(20)(k0)
+ sd $21,REGIDX(21)(k0)
+ sd $22,REGIDX(22)(k0)
+ sd $23,REGIDX(23)(k0)
+ sd $24,REGIDX(24)(k0)
+ sd $25,REGIDX(25)(k0)
+ sd $26,REGIDX(26)(k0) /* k0 */
+ sd $27,REGIDX(27)(k0)
+ sd $28,REGIDX(28)(k0)
+ sd $29,REGIDX(29)(k0)
+ sd $30,REGIDX(30)(k0)
+ sd $31,REGIDX(31)(k0)
+ .set at
+
+# Save some CP0 registers here.
+#define LSAVECP0(cp0,idx) \
+ dmfc0 t0,cp0 ; \
+ sd t0,REGIDX(idx)(k0)
+
+ LSAVECP0(C0_INX,32)
+ LSAVECP0(C0_RAND,33)
+ LSAVECP0(C0_TLBLO0,34)
+ LSAVECP0(C0_TLBLO1,35)
+ LSAVECP0(C0_CTEXT,36)
+ LSAVECP0(C0_PGMASK,37)
+ LSAVECP0(C0_WIRED,38)
+ LSAVECP0(C0_BADVADDR,39)
+ LSAVECP0(C0_COUNT,40)
+ LSAVECP0(C0_TLBHI,41)
+ LSAVECP0(C0_COMPARE,42)
+ LSAVECP0(C0_SR,43)
+ LSAVECP0(C0_CAUSE,44)
+ LSAVECP0(C0_EPC,45)
+ LSAVECP0(C0_PRID,46)
+ LSAVECP0(C0_CONFIG,47)
+ LSAVECP0(C0_LLADDR,48)
+ LSAVECP0(C0_WATCHLO,49)
+ LSAVECP0(C0_WATCHHI,50)
+ LSAVECP0(C0_XCTEXT,51)
+ LSAVECP0(C0_ECC,52)
+ LSAVECP0(C0_CACHEERR,53)
+ LSAVECP0(C0_TAGLO,54)
+ LSAVECP0(C0_TAGHI,55)
+ LSAVECP0(C0_ERREPC,56)
+
+
+ move a0,k0 /* pass addr of regs */
+ la gp,_gp
+ LR sp,mem_heapstart
+ ADD sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8)
+ jal vapi_dodumpregs /* dump registers in 'C' */
+
+ .set noat
+ la k0,vapi_regsave
+ ld $1,REGIDX(1)(k0)
+ ld $2,REGIDX(2)(k0)
+ ld $3,REGIDX(3)(k0)
+ ld $4,REGIDX(4)(k0)
+ ld $5,REGIDX(5)(k0)
+ ld $6,REGIDX(6)(k0)
+ ld $7,REGIDX(7)(k0)
+ ld $8,REGIDX(8)(k0)
+ ld $9,REGIDX(9)(k0)
+ ld $10,REGIDX(10)(k0)
+ ld $11,REGIDX(11)(k0)
+ ld $12,REGIDX(12)(k0)
+ ld $13,REGIDX(13)(k0)
+ ld $14,REGIDX(14)(k0)
+ ld $15,REGIDX(15)(k0)
+ ld $16,REGIDX(16)(k0)
+ ld $17,REGIDX(17)(k0)
+ ld $18,REGIDX(18)(k0)
+ ld $19,REGIDX(19)(k0)
+ ld $20,REGIDX(20)(k0)
+ ld $21,REGIDX(21)(k0)
+ ld $22,REGIDX(22)(k0)
+ ld $23,REGIDX(23)(k0)
+ ld $24,REGIDX(24)(k0)
+ ld $25,REGIDX(25)(k0)
+ /*ld $26,REGIDX(26)(k0) don't restore k0 */
+ ld $27,REGIDX(27)(k0)
+ ld $28,REGIDX(28)(k0)
+ ld $29,REGIDX(29)(k0)
+ ld $30,REGIDX(30)(k0)
+ ld $31,REGIDX(31)(k0)
+ .set at
+
+ j ra
+
+END(vapi_dumpgprs)
+
+
+/* *********************************************************************
+ * VAPI_SETLOG(start,end)
+ *
+ * Set the address of the log buffer. This call is required
+ * before any data will be stored in the log.
+ *
+ * Input parameters:
+ * a0 - start of log buffer, 64-bit aligned
+ * a1 - end of log buffer, 64-bit aligned
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * k0 - scratch register for CFE
+ ********************************************************************* */
+
+LEAF(vapi_setlog)
+
+ SAVETEMPS(vapi_regsave)
+
+ sd a0,vapi_logstart
+ sd a0,vapi_logptr
+ sd a1,vapi_logend
+ sd zero,vapi_logover
+
+ RESTORETEMPS(vapi_regsave)
+
+ j ra
+
+END(vapi_setlog)
+
+/* *********************************************************************
+ * VAPI_LOGTRACE(id)
+ *
+ * Store a the contents of the trace buffer to the log
+ *
+ * Input parameters:
+ * a0 - low 32 bits are the ID code to store with the entry
+ * in the log.
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * k0 - scratch register for CFE
+ ********************************************************************* */
+
+LEAF(vapi_logtrace)
+
+ j ra
+
+END(vapi_logtrace)
+
+
+/* *********************************************************************
+ * VAPI_LOGSINGLE(id,value)
+ *
+ * Store a single value in the log.
+ *
+ * Input parameters:
+ * a0 - low 32 bits are the ID code to store with the entry
+ * in the log.
+ * a1 - value to store in the log
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * k0 - scratch register for CFE
+ ********************************************************************* */
+
+LEAF(vapi_logsingle)
+
+
+ SAVETEMPS(vapi_regsave)
+
+ CHECKPTR(99f)
+
+ SETRECTYPE(VAPI_FMT_DATA,a0)
+ SETRECLEN_CONST(1)
+
+ sd a1,VAPI_REC_DATA(RECPTR)
+
+ add RECPTR,32 # one record
+ sd RECPTR,vapi_logptr
+
+99: RESTORETEMPS(vapi_regsave)
+
+ j ra
+
+END(vapi_logsingle)
+
+/* *********************************************************************
+ * VAPI_LOGDATA(id,addr,cnt)
+ *
+ * Store multiple values in the log
+ *
+ * Input parameters:
+ * a0 - low 32 bits are the ID code to store with the entry
+ * in the log.
+ * a1 - Address of values to store in the log
+ * a2 - number of 64-bit values to store in the log
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * k0 - scratch register for CFE
+ ********************************************************************* */
+
+LEAF(vapi_logdata)
+
+ SAVETEMPS(vapi_regsave)
+
+ CHECKPTR(99f)
+
+ SETRECTYPE(VAPI_FMT_BUFFER,a0)
+
+ add t1,RECPTR,VAPI_REC_DATA # a1 = ptr to data ara
+
+ sd a1,0(t1)
+ add t1,8
+
+ move k0,a2 # counter for words
+
+1: beq k0,zero,2f
+ ld t0,0(a1)
+ sd t0,0(t1)
+ add a1,8
+ add t1,8
+ sub k0,1
+ b 1b
+
+2: add k0,a2,1 # total number of words
+ SETRECLEN_REG(k0)
+ sll k0,k0,3 # number of words we wrote
+ add k0,24 # size of header
+ add RECPTR,k0
+ sd RECPTR,vapi_logptr
+
+99: RESTORETEMPS(vapi_regsave)
+
+ j ra
+
+END(vapi_logdata)
+
+
+/* *********************************************************************
+ * VAPI_SAVESOC(id)
+ *
+ * Save the SOC registers in the log
+ *
+ * Input parameters:
+ * a0 - low 32 bits are the ID code to store with the entry
+ * in the log
+ * a1 - bitmask of SOC agents to save
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * k0 - scratch register for CFE
+ ********************************************************************* */
+
+LEAF(vapi_savesoc)
+
+ SAVETEMPS(vapi_regsave)
+
+ CHECKPTR(99f)
+
+ li t0,VAPI_CFESEAL | VAPI_FMT_SOC
+ dsll t0,t0,32
+ or t0,a0
+ mfc0 t1,C0_PRID
+ srl t1,t1,25
+ and t1,t1,7
+ sll t1,t1,VAPI_PRNUM_SHIFT
+ or t0,t0,t1
+ ld t1,vapi_logptr
+
+ sd t0,VAPI_REC_SIGNATURE(t1)
+ mfc0 t0,C0_COUNT
+ dsll t0,t0,32
+ sd t0,VAPI_REC_SIZE(t1)
+ sd ra,VAPI_REC_RA(t1)
+
+ move a2,zero # Counts how many we write
+
+ la t2,vapi_socregs
+
+1: lw t0,0(t2) # get flags
+ beq t0,zero,2f
+ and t0,t0,a1 # test flags
+ beq t0,zero,3f # skip if no flags set
+
+ lw t0,4(t2) # get address of register
+
+ sd t0,VAPI_REC_DATA(t1) # store address of register
+ add t1,8 # next destination addr
+ add a2,1 # count the words written
+
+ or t0,K1BASE # Make K1seg
+ ld t0,0(t0) # Read SOC register
+
+ sd t0,VAPI_REC_DATA(t1) # Store in log
+ add t1,8 # next destination addr
+ add a2,1 # count the words written
+
+3: add t2,8 # next reg from table
+
+ b 1b
+
+2: ld t0,vapi_logptr # get original pointer
+ ld a1,VAPI_REC_SIZE(t0) # Get C0_COUNT value
+ or a1,a2 # OR in the record size
+ sd a1,VAPI_REC_SIZE(t0) # put the record size back
+
+ add t1,24 # Account for extra fields in record
+ sd t1,vapi_logptr # Update the pointer
+
+99: RESTORETEMPS(vapi_regsave)
+
+ j ra
+
+END(vapi_savesoc)
+
+/* *********************************************************************
+ * VAPI_LOGGPRS(id)
+ *
+ * Save the general purpose registers and certain CP0 values
+ * in the log.
+ *
+ * Input parameters:
+ * a0 - low 32 bits are the ID code to store with the entry
+ * in the log
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * k0 - scratch register for CFE
+ ********************************************************************* */
+
+#define REGLOG(x) (VAPI_REC_DATA+REGIDX(x))
+#define MAXREGS 57
+#define REGLOGMAX REGLOG(MAXREGS)
+
+LEAF(vapi_loggprs)
+
+ SAVETEMPS(vapi_regsave)
+ CHECKPTR(99f)
+
+ .set noat
+ ld k0,vapi_logptr
+ sd $0,REGLOG(0)(k0)
+ sd $1,REGLOG(1)(k0)
+ sd $2,REGLOG(2)(k0)
+ sd $3,REGLOG(3)(k0)
+ sd $4,REGLOG(4)(k0)
+ sd $5,REGLOG(5)(k0)
+ sd $6,REGLOG(6)(k0)
+ sd $7,REGLOG(7)(k0)
+ sd $8,REGLOG(8)(k0)
+ sd $9,REGLOG(9)(k0)
+ sd $10,REGLOG(10)(k0)
+ sd $11,REGLOG(11)(k0)
+ sd $12,REGLOG(12)(k0)
+ sd $13,REGLOG(13)(k0)
+ sd $14,REGLOG(14)(k0)
+ sd $15,REGLOG(15)(k0)
+ sd $16,REGLOG(16)(k0)
+ sd $17,REGLOG(17)(k0)
+ sd $18,REGLOG(18)(k0)
+ sd $19,REGLOG(19)(k0)
+ sd $20,REGLOG(20)(k0)
+ sd $21,REGLOG(21)(k0)
+ sd $22,REGLOG(22)(k0)
+ sd $23,REGLOG(23)(k0)
+ sd $24,REGLOG(24)(k0)
+ sd $25,REGLOG(25)(k0)
+ sd $26,REGLOG(26)(k0)
+ sd $27,REGLOG(27)(k0)
+ sd $28,REGLOG(28)(k0)
+ sd $29,REGLOG(29)(k0)
+ sd $30,REGLOG(30)(k0)
+ sd $31,REGLOG(31)(k0)
+ .set at
+
+
+# Save some CP0 registers here.
+#define SAVECP0(cp0,idx) \
+ dmfc0 t0,cp0 ; \
+ sd t0,REGLOG(idx)(k0)
+
+ SAVECP0(C0_INX,32)
+ SAVECP0(C0_RAND,33)
+ SAVECP0(C0_TLBLO0,34)
+ SAVECP0(C0_TLBLO1,35)
+ SAVECP0(C0_CTEXT,36)
+ SAVECP0(C0_PGMASK,37)
+ SAVECP0(C0_WIRED,38)
+ SAVECP0(C0_BADVADDR,39)
+ SAVECP0(C0_COUNT,40)
+ SAVECP0(C0_TLBHI,41)
+ SAVECP0(C0_COMPARE,42)
+ SAVECP0(C0_SR,43)
+ SAVECP0(C0_CAUSE,44)
+ SAVECP0(C0_EPC,45)
+ SAVECP0(C0_PRID,46)
+ SAVECP0(C0_CONFIG,47)
+ SAVECP0(C0_LLADDR,48)
+ SAVECP0(C0_WATCHLO,49)
+ SAVECP0(C0_WATCHHI,50)
+ SAVECP0(C0_XCTEXT,51)
+ SAVECP0(C0_ECC,52)
+ SAVECP0(C0_CACHEERR,53)
+ SAVECP0(C0_TAGLO,54)
+ SAVECP0(C0_TAGHI,55)
+ SAVECP0(C0_ERREPC,56)
+
+ SETRECTYPE(VAPI_FMT_GPRS,a0)
+ SETRECLEN_CONST(MAXREGS)
+ add RECPTR,REGLOGMAX
+ sd RECPTR,vapi_logptr
+
+99: RESTORETEMPS(vapi_regsave)
+
+ j ra # go home
+
+END(vapi_loggprs)
+
+
+/* *********************************************************************
+ * VAPI_LOGFPRS(id)
+ *
+ * Save the floating point unit's registers
+ * in the log.
+ *
+ * Input parameters:
+ * a0 - low 32 bits are the ID code to store with the entry
+ * in the log
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * k0 - scratch register for CFE
+ ********************************************************************* */
+
+
+#define SAVEFPR(cp1,idx) \
+ dmfc1 t0,cp1 ; \
+ sd t0,FPREGLOG(idx)(k0)
+#define SAVECP1(cp1,idx) \
+ cfc1 t0,cp1 ; \
+ sd t0,FPREGLOG(idx)(k0)
+
+#define FPREGLOG(x) (VAPI_REC_DATA+REGIDX(x))
+#define FPMAXREGS 37
+#define FPREGLOGMAX FPREGLOG(FPMAXREGS)
+
+LEAF(vapi_logfprs)
+
+ SAVETEMPS(vapi_regsave)
+ CHECKPTR(99f)
+
+ ld k0,vapi_logptr
+ SAVEFPR($0,0)
+ SAVEFPR($1,1)
+ SAVEFPR($2,2)
+ SAVEFPR($3,3)
+ SAVEFPR($4,4)
+ SAVEFPR($5,5)
+ SAVEFPR($6,6)
+ SAVEFPR($7,7)
+ SAVEFPR($8,8)
+ SAVEFPR($9,9)
+ SAVEFPR($10,10)
+ SAVEFPR($11,11)
+ SAVEFPR($12,12)
+ SAVEFPR($13,13)
+ SAVEFPR($14,14)
+ SAVEFPR($15,15)
+ SAVEFPR($16,16)
+ SAVEFPR($17,17)
+ SAVEFPR($18,18)
+ SAVEFPR($19,19)
+ SAVEFPR($20,20)
+ SAVEFPR($21,21)
+ SAVEFPR($22,22)
+ SAVEFPR($23,23)
+ SAVEFPR($24,24)
+ SAVEFPR($25,25)
+ SAVEFPR($26,26)
+ SAVEFPR($27,27)
+ SAVEFPR($28,28)
+ SAVEFPR($29,29)
+ SAVEFPR($30,30)
+ SAVEFPR($31,31)
+
+ SAVECP1($0,32) /* FIR */
+ SAVECP1($31,33) /* Status */
+ SAVECP1($25,34) /* condition codes */
+ SAVECP1($26,35) /* Exceptions */
+ SAVECP1($28,36) /* enables */
+
+ SETRECTYPE(VAPI_FMT_FPRS,a0)
+ SETRECLEN_CONST(FPMAXREGS)
+ add RECPTR,FPREGLOGMAX
+ sd RECPTR,vapi_logptr
+
+99: RESTORETEMPS(vapi_regsave)
+
+ j ra # go home
+
+END(vapi_logfprs)
+
+/* *********************************************************************
+ * VAPI_PUTS(string)
+ *
+ * Display a string on the console
+ *
+ * Input parameters:
+ * a0 - pointer to null-terminated string
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * k0 - scratch register for CFE
+ ********************************************************************* */
+
+LEAF(vapi_puts)
+
+ .set noat
+ la k0,vapi_regsave
+ sd $0,REGIDX(0)(k0)
+ sd $1,REGIDX(1)(k0)
+ sd $2,REGIDX(2)(k0)
+ sd $3,REGIDX(3)(k0)
+ sd $4,REGIDX(4)(k0)
+ sd $5,REGIDX(5)(k0)
+ sd $6,REGIDX(6)(k0)
+ sd $7,REGIDX(7)(k0)
+ sd $8,REGIDX(8)(k0)
+ sd $9,REGIDX(9)(k0)
+ sd $10,REGIDX(10)(k0)
+ sd $11,REGIDX(11)(k0)
+ sd $12,REGIDX(12)(k0)
+ sd $13,REGIDX(13)(k0)
+ sd $14,REGIDX(14)(k0)
+ sd $15,REGIDX(15)(k0)
+ sd $16,REGIDX(16)(k0)
+ sd $17,REGIDX(17)(k0)
+ sd $18,REGIDX(18)(k0)
+ sd $19,REGIDX(19)(k0)
+ sd $20,REGIDX(20)(k0)
+ sd $21,REGIDX(21)(k0)
+ sd $22,REGIDX(22)(k0)
+ sd $23,REGIDX(23)(k0)
+ sd $24,REGIDX(24)(k0)
+ sd $25,REGIDX(25)(k0)
+ sd $26,REGIDX(26)(k0) /* k0 */
+ sd $27,REGIDX(27)(k0)
+ sd $28,REGIDX(28)(k0)
+ sd $29,REGIDX(29)(k0)
+ sd $30,REGIDX(30)(k0)
+ sd $31,REGIDX(31)(k0)
+ .set at
+
+ la gp,_gp
+ LR sp,mem_heapstart
+ ADD sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8)
+ jal vapi_doputs /* dump registers in 'C' */
+
+ .set noat
+ la k0,vapi_regsave
+ ld $1,REGIDX(1)(k0)
+ ld $2,REGIDX(2)(k0)
+ ld $3,REGIDX(3)(k0)
+ ld $4,REGIDX(4)(k0)
+ ld $5,REGIDX(5)(k0)
+ ld $6,REGIDX(6)(k0)
+ ld $7,REGIDX(7)(k0)
+ ld $8,REGIDX(8)(k0)
+ ld $9,REGIDX(9)(k0)
+ ld $10,REGIDX(10)(k0)
+ ld $11,REGIDX(11)(k0)
+ ld $12,REGIDX(12)(k0)
+ ld $13,REGIDX(13)(k0)
+ ld $14,REGIDX(14)(k0)
+ ld $15,REGIDX(15)(k0)
+ ld $16,REGIDX(16)(k0)
+ ld $17,REGIDX(17)(k0)
+ ld $18,REGIDX(18)(k0)
+ ld $19,REGIDX(19)(k0)
+ ld $20,REGIDX(20)(k0)
+ ld $21,REGIDX(21)(k0)
+ ld $22,REGIDX(22)(k0)
+ ld $23,REGIDX(23)(k0)
+ ld $24,REGIDX(24)(k0)
+ ld $25,REGIDX(25)(k0)
+ /*ld $26,REGIDX(26)(k0) don't restore k0 */
+ ld $27,REGIDX(27)(k0)
+ ld $28,REGIDX(28)(k0)
+ ld $29,REGIDX(29)(k0)
+ ld $30,REGIDX(30)(k0)
+ ld $31,REGIDX(31)(k0)
+ .set at
+
+ j ra
+
+END(vapi_puts)
+
+/* *********************************************************************
+ * VAPI_SETLEDS(leds)
+ *
+ * Set the onboard LEDS on the swarm board.
+ *
+ * Input parameters:
+ * a0 - LED value, "ABCD" is 0x41424344
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * k0 - scratch register for CFE
+ ********************************************************************* */
+
+
+LEAF(vapi_setleds)
+
+ SAVETEMPS(vapi_regsave)
+
+ jal board_setleds
+
+ RESTORETEMPS(vapi_regsave)
+
+ j ra
+
+END(vapi_setleds)
+
+/* *********************************************************************
+ * VAPI_KSEG1_SWITCH
+ *
+ * Hack the return address so we will come back in KSEG1 (uncached)
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(vapi_kseg1_switch)
+
+ and ra,(K0SIZE-1)
+ or ra,K1BASE
+ jr ra
+
+END(vapi_kseg1_switch)
+
+
+/* *********************************************************************
+ * VAPI_RUN()
+ *
+ * Jump to the diagnostic program, which must be loaded at the
+ * special address (typically 8002_0000). First we flush the
+ * cache, then set magic #'s in the mailbox. Finally, the core
+ * is reset. On restart, we do minimal initialization and jump
+ * directly to the diagnostic.
+ *
+ * Input parameters:
+ * a0 - nonzero to restart uncached.
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(vapi_run)
+
+ /*
+ * Run uncached
+ */
+
+ bal vapi_kseg1_switch # now running in KSEG1
+
+ /*
+ * Flush the caches
+ */
+
+ move s0,a0 # L2 flush trashes A0
+ CALLKSEG1(sb1250_l1cache_flush_d)
+ CALLKSEG1(sb1250_l1cache_inval_i)
+ CALLKSEG1(sb1250_l2cache_flush)
+ move a0,s0
+
+#ifdef _P5064_
+
+ /* In the case of the P5064, just jump directly to the entry point */
+
+ li t0,VAPI_DIAG_ENTRY
+ j t0
+
+#else
+
+ /*
+ * Set the magic code in the mailbox.
+ */
+
+ li t0,-1
+ la t1,PHYS_TO_K1(A_IMR_REGISTER(0,R_IMR_MAILBOX_CLR_CPU))
+ sd t0,0(t1)
+
+ dli t0,VAPI_MAGIC_NUMBER
+ beq a0,0,1f
+ dli t0,VAPI_MAGIC_NUMBER_UNC
+ beq a0,1,1f
+ dli t0,VAPI_MAGIC_NUMBER_MC
+1: la t1,PHYS_TO_K1(A_IMR_REGISTER(0,R_IMR_MAILBOX_SET_CPU))
+ sd t0,0(t1)
+
+ /*
+ * Whack the reset line.
+ */
+#if defined(_PTSWARM_)
+ li k0,PHYS_TO_K1(0x1B0A0000+32+8*3)
+#else
+ li k0,PHYS_TO_K1(0x100A0000+32+8*3)
+#endif
+ li k1,'!'
+
+ li t1,PHYS_TO_K1(A_SCD_SYSTEM_CFG)
+ ld t2,0(t1)
+ dli t0,M_SYS_CPU_RESET_0 | M_SYS_CPU_RESET_1
+ or t2,t2,t0
+ bal vapi_kseg0_switch
+ .align 5
+#if defined(_CSWARM_) || defined(_SWARM_) || defined(_PTSWARM_)
+ sb k1,0(k0)
+#else
+ nop
+#endif
+ sync /* flush the write buffer */
+ sd t2,0(t1)
+1: b 1b
+
+ /*
+ * And he never returned, no he never returned... and his fate
+ * is still unknown, he will ride forever 'neath the cycles of
+ * the SB1, he's the core that never returned!
+ */
+#endif
+
+
+
+END(vapi_run)
+
+
+LEAF(vapi_flushtest)
+
+ move s1,ra
+
+ /*
+ * Run uncached
+ */
+
+ bal vapi_kseg1_switch # now running in KSEG1
+
+ /*
+ * Flush the caches
+ */
+
+ move s0,a0 # L2 flush trashes A0
+ CALLKSEG1(sb1250_l1cache_flush_d)
+ CALLKSEG1(sb1250_l1cache_inval_i)
+ CALLKSEG1(sb1250_l2cache_flush)
+ move a0,s0
+
+ /*
+ * Back to cached
+ */
+
+ bal vapi_kseg0_switch # now running in KSEG1
+
+ move ra,s1
+ j ra
+
+END(vapi_flushtest)
+
+
+#endif /* CFG_VAPI */
+
+/* *********************************************************************
+ * End
+ ********************************************************************* */
+
+
diff --git a/cfe/cfe/verif/vapi.h b/cfe/cfe/verif/vapi.h
new file mode 100644
index 0000000..1deb8a5
--- /dev/null
+++ b/cfe/cfe/verif/vapi.h
@@ -0,0 +1,242 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Verification Test APIs File: vapi.h
+ *
+ * This module contains special low-level routines for use
+ * by verification programs.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#define VAPI_EPTSEAL 0x56415049
+#define VAPI_CFESEAL 0xCFE10000
+#define VAPI_SEAL_MASK 0xFFFF0000
+#define VAPI_FMT_MASK 0x000000FF
+#define VAPI_PRID_MASK 0x0000FF00
+
+#define VAPI_DIAG_ENTRY 0x80020000
+#define VAPI_DIAG_ENTRY_UNC 0xA0020000
+#define VAPI_DIAG_ENTRY_MC 0xBFD00000
+#define VAPI_MAGIC_NUMBER 0x1CFE2CFE3CFE4CFE
+#define VAPI_MAGIC_NUMBER_UNC 0x0CFE1CFE2CFE3CFE
+#define VAPI_MAGIC_NUMBER_MC 0xACFEBCFECCFEDCFE
+
+#define VAPI_FMT_GPRS 0
+#define VAPI_FMT_SOC 1
+#define VAPI_FMT_DATA 2
+#define VAPI_FMT_BUFFER 3
+#define VAPI_FMT_TRACE 4
+#define VAPI_FMT_EXIT 5
+#define VAPI_FMT_FPRS 6
+
+#define VAPI_PRNUM_SHIFT 8
+
+#define VAPI_REC_SIGNATURE 0
+#define VAPI_REC_SIZE 8
+#define VAPI_REC_RA 16
+#define VAPI_REC_DATA 24
+
+#define VAPI_IDX_SIGNATURE 0
+#define VAPI_IDX_SIZE 1
+#define VAPI_IDX_RA 2
+#define VAPI_IDX_DATA 3
+
+
+#define VAPI_FUNC_EXIT 0x9fc00510
+#define VAPI_FUNC_DUMPGPRS 0x9fc00520
+#define VAPI_FUNC_SETLOG 0x9fc00530
+#define VAPI_FUNC_LOGVALUE 0x9fc00540
+#define VAPI_FUNC_LOGDATA 0x9fc00550
+#define VAPI_FUNC_LOGTRACE 0x9fc00560
+#define VAPI_FUNC_LOGSOC 0x9fc00570
+#define VAPI_FUNC_LOGGPRS 0x9fc00580
+#define VAPI_FUNC_DUMPSTRING 0x9fc00590
+#define VAPI_FUNC_SETLEDS 0x9fc005a0
+#define VAPI_FUNC_LOGFPRS 0x9fc005b0
+
+
+#define VAPI_LOG_SETBUF(start,end) \
+ .set push ; \
+ .set reorder ; \
+ la a0, start ; \
+ la a1, end ; \
+ li k0, VAPI_FUNC_SETLOG ; \
+ jalr k0 ; \
+ .set pop
+
+#define VAPI_EXIT_CONST(val) \
+ .set push ; \
+ .set reorder ; \
+ li a0, val ; \
+ li k0, VAPI_FUNC_EXIT ; \
+ jr k0 ; \
+ .set pop
+
+#define VAPI_EXIT_REG(val) \
+ .set push ; \
+ .set reorder ; \
+ move a0, val ; \
+ li k0, VAPI_FUNC_EXIT ; \
+ jr k0 ; \
+ .set pop
+
+#define VAPI_LOG_CONST(id,value) \
+ .set push ; \
+ .set reorder ; \
+ li a0, id ; \
+ li a1, value ; \
+ li k0, VAPI_FUNC_LOGVALUE ; \
+ jalr k0 ; \
+ .set pop
+
+#define VAPI_LOG_REG(id,value) \
+ .set push ; \
+ .set reorder ; \
+ li a0, id ; \
+ move a1, value ; \
+ li k0, VAPI_FUNC_LOGVALUE ; \
+ jalr k0 ; \
+ .set pop
+
+#define VAPI_LOG_BUFFER(id,addr,nwords) \
+ .set push ; \
+ .set reorder ; \
+ li a0,id ; \
+ la a1,addr ; \
+ li a2,nwords ; \
+ li k0, VAPI_FUNC_LOGDATA ; \
+ jalr k0 ; \
+ .set pop
+
+#define VAPI_PUTS(text) \
+ .set push ; \
+ .set reorder ; \
+ b 1f ; \
+2: .asciz text ; \
+ .align 4 ; \
+1: la a0, 2b ; \
+ li k0, VAPI_FUNC_DUMPSTRING ; \
+ jalr k0 ; \
+ .set pop
+
+#define VAPI_PRINTGPRS() \
+ .set push ; \
+ .set reorder ; \
+ li k0, VAPI_FUNC_DUMPGPRS ; \
+ jalr k0 ; \
+ .set pop
+
+#define VAPI_LOG_GPRS(id) \
+ .set push ; \
+ .set reorder ; \
+ li a0, id ; \
+ li k0, VAPI_FUNC_LOGGPRS ; \
+ jalr k0 ; \
+ .set pop
+
+#define VAPI_LOG_FPRS(id) \
+ .set push ; \
+ .set reorder ; \
+ li a0, id ; \
+ li k0, VAPI_FUNC_LOGFPRS ; \
+ jalr k0 ; \
+ .set pop
+
+#define VAPI_LOG_TRACE(id) \
+ .set push ; \
+ .set reorder ; \
+ li a0, id ; \
+ li k0, VAPI_FUNC_LOGTRACE ; \
+ jalr k0 ; \
+ .set pop
+
+#define VAPI_LOG_SOCSTATE(id,bits) \
+ .set push ; \
+ .set reorder ; \
+ li a0, id ; \
+ li a1, bits ; \
+ li k0, VAPI_FUNC_LOGSOC ; \
+ jalr k0 ; \
+ .set pop
+
+#define VAPI_SETLEDS(a,b,c,d) \
+ .set push ; \
+ .set reorder ; \
+ li a0, ((a) << 24) | ((b) << 16) | ((c) << 8) | (d) ; \
+ li k0, VAPI_FUNC_SETLEDS ; \
+ jalr k0 ; \
+ .set pop
+
+#ifndef SOC_AGENT_MC0
+#define SOC_AGENT_MC0 0x00000001
+#define SOC_AGENT_MC1 0x00000002
+#define SOC_AGENT_MC 0x00000003
+#define SOC_AGENT_L2 0x00000004
+#define SOC_AGENT_MACDMA0 0x00000008
+#define SOC_AGENT_MACDMA1 0x00000010
+#define SOC_AGENT_MACDMA2 0x00000020
+#define SOC_AGENT_MACDMA 0x00000038
+#define SOC_AGENT_MACRMON0 0x00000040
+#define SOC_AGENT_MACRMON1 0x00000080
+#define SOC_AGENT_MACRMON2 0x00000100
+#define SOC_AGENT_MACRMON 0x000001C0
+#define SOC_AGENT_MAC0 0x00000200
+#define SOC_AGENT_MAC1 0x00000400
+#define SOC_AGENT_MAC2 0x00000800
+#define SOC_AGENT_MAC 0x00000E00
+#define SOC_AGENT_DUART 0x00001000
+#define SOC_AGENT_GENCS 0x00002000
+#define SOC_AGENT_GEN 0x00004000
+#define SOC_AGENT_GPIO 0x00008000
+#define SOC_AGENT_SMBUS0 0x00010000
+#define SOC_AGENT_SMBUS1 0x00020000
+#define SOC_AGENT_SMBUS 0x00030000
+#define SOC_AGENT_TIMER 0x00040000
+#define SOC_AGENT_SCD 0x00080000
+#define SOC_AGENT_BUSERR 0x00100000
+#define SOC_AGENT_DM 0x00200000
+#define SOC_AGENT_IMR0 0x00400000
+#define SOC_AGENT_IMR1 0x00800000
+#define SOC_AGENT_IMR 0x00C00000
+#endif
+
+
+
diff --git a/cfe/cfe/verif/vapisubr.c b/cfe/cfe/verif/vapisubr.c
new file mode 100644
index 0000000..1ec130a
--- /dev/null
+++ b/cfe/cfe/verif/vapisubr.c
@@ -0,0 +1,122 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Verification Test APIs File: vapisubr.c
+ *
+ * This module contains special low-level routines for use
+ * by verification programs. The routines here are the "C"
+ * routines for higher-level functions.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "sbmips.h"
+#include "bsp_config.h"
+#include "lib_types.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "cfe_console.h"
+
+#if CFG_VAPI
+
+void vapi_doputs(char *str);
+void vapi_dodumpregs(uint64_t *gprs);
+
+const static char * const gpregnames[] = {
+ "$0/zero","$1/AT","$2/v0","$3/v1","$4/a0","$5/a1","$6/a2","$7/a3",
+ "$8/t0","$9/t1","$10/t2","$11/t3","$12/t4","$13/t5","$14/t6","$15/t7",
+ "$16/s0","$17/s1","$18/s2","$19/s3","$20/s4","$21/s5","$22/s6","$23/s7",
+ "$24/t8","$25/t9","$26/k0","$27/k1","$28/gp","$29/sp","$30/fp","$31/ra",
+ "INX",
+ "RAND",
+ "TLBLO0",
+ "TLBLO1",
+ "CTEXT",
+ "PGMASK",
+ "WIRED",
+ "BADVADDR",
+ "COUNT",
+ "TLBHI",
+ "COMPARE",
+ "SR",
+ "CAUSE",
+ "EPC",
+ "PRID",
+ "CONFIG",
+ "LLADDR",
+ "WATCHLO",
+ "WATCHHI",
+ "XCTEXT",
+ "ECC",
+ "CACHEERR",
+ "TAGLO",
+ "TAGHI",
+ "ERREPC"};
+
+
+
+
+void vapi_doputs(char *str)
+{
+ xprintf("# %s\n",str);
+}
+
+void vapi_dodumpregs(uint64_t *gprs)
+{
+ int cnt = sizeof(gpregnames)/sizeof(char *);
+ int idx;
+
+ xprintf("# GPRS:\n");
+ for (idx = 0; idx < cnt; idx++) {
+ if ((idx & 1) == 0) xprintf("# ");
+ xprintf(" %8s=%016llX ",gpregnames[idx],gprs[idx]);
+ if ((idx & 1) == 1) xprintf("\n");
+ }
+ xprintf("\n");
+
+}
+
+#endif /* CFG_VAPI */
+
+/* *********************************************************************
+ * End
+ ********************************************************************* */
+
+
diff --git a/cfe/cfe/verif/vapitest.S b/cfe/cfe/verif/vapitest.S
new file mode 100644
index 0000000..4199f4e
--- /dev/null
+++ b/cfe/cfe/verif/vapitest.S
@@ -0,0 +1,108 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Verification Test APIs File: vapitest.S
+ *
+ * This module contains special low-level routines for use
+ * by verification programs.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "sbmips.h"
+#include "bsp_config.h"
+
+#if CFG_VAPI
+
+#if (CFG_EMBEDDED_PIC)
+#error "CFG_VAPI is not compatible with relocatable code"
+#endif
+
+
+#include "vapi.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+ .text
+
+testbuf: .dword 0x123456789ABCDEF0
+ .dword 0xAABBCCDD
+ .dword 0xAABBCCDD
+ .dword 0xAABBCCDD
+ .dword 0xAABBCCDD
+ .dword 0xAABBCCDD
+ .dword 0xAABBCCDD
+ .dword 0xAABBCCDD
+ .dword 0xAABBCCDD
+ .dword 0xFEDCBA9876543210
+
+LEAF(vapitest)
+
+ sub sp,8
+ sd ra,0(sp)
+
+ VAPI_LOG_SETBUF(0x80200000,0x80300000)
+
+
+ VAPI_LOG_CONST(0x100,0xABCDEF)
+ VAPI_LOG_REG(0x101,sp)
+ VAPI_LOG_BUFFER(0x102,testbuf,10)
+ VAPI_PUTS("Hello world.\n")
+ VAPI_LOG_SOCSTATE(0x103,SOC_AGENT_DUART)
+ VAPI_PRINTGPRS();
+ VAPI_LOG_CONST(0x1EE,0xEEEEEEEE)
+ VAPI_LOG_GPRS(0x199)
+ VAPI_SETLEDS('V','A','P','I')
+
+ ld ra,0(sp)
+ add sp,8
+ j ra
+
+END(vapitest)
+
+
+#endif /* CFG_VAPI */
+
+/* *********************************************************************
+ * End
+ ********************************************************************* */
+
+
diff --git a/cfe/cfe/x86emu/LICENSE b/cfe/cfe/x86emu/LICENSE
new file mode 100644
index 0000000..a3ede4a
--- /dev/null
+++ b/cfe/cfe/x86emu/LICENSE
@@ -0,0 +1,17 @@
+ License information
+ -------------------
+
+The x86emu library is under a BSD style license, comaptible
+with the XFree86 and X licenses used by XFree86. The
+original x86emu libraries were under the GNU General Public
+License. Due to license incompatibilities between the GPL
+and the XFree86 license, the original authors of the code
+decided to allow a license change. If you have submitted
+code to the original x86emu project, and you don't agree
+with the license change, please contact us and let you
+know. Your code will be removed to comply with your wishes.
+
+If you have any questions about this, please send email to
+x86emu@linuxlabs.com or KendallB@scitechsoft.com for
+clarification.
+
diff --git a/cfe/cfe/x86emu/Makefile b/cfe/cfe/x86emu/Makefile
new file mode 100644
index 0000000..6b02c1a
--- /dev/null
+++ b/cfe/cfe/x86emu/Makefile
@@ -0,0 +1,2 @@
+
+ALLOBJS += debug.o decode.o fpu.o ops.o ops2.o prim_ops.o sys.o
diff --git a/cfe/cfe/x86emu/README b/cfe/cfe/x86emu/README
new file mode 100644
index 0000000..c7351ba
--- /dev/null
+++ b/cfe/cfe/x86emu/README
@@ -0,0 +1,12 @@
+
+This is a simple X86 emulator. The original source for this
+was taken from the XFree86 project. This code is used to
+interpret the X86 instructions in the ROM on the VGA
+adapter to initialize the card to text mode. Once initialized,
+this emulator is no longer needed.
+
+** Read the 'LICENSE' file before using this in production code **
+
+The XFree86 license is similar to the BSD license.
+
+
diff --git a/cfe/cfe/x86emu/debug.c b/cfe/cfe/x86emu/debug.c
new file mode 100644
index 0000000..3e26a50
--- /dev/null
+++ b/cfe/cfe/x86emu/debug.c
@@ -0,0 +1,462 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: This file contains the code to handle debugging of the
+* emulator.
+*
+****************************************************************************/
+/* $XFree86: xc/extras/x86emu/src/x86emu/debug.c,v 1.4 2000/04/17 16:29:45 eich Exp $ */
+
+#include "x86emu/x86emui.h"
+#ifdef IN_MODULE
+#include "xf86_ansic.h"
+#else
+#include <stdarg.h>
+#ifndef _CFE_
+#include <stdlib.h>
+#endif
+#endif
+
+#ifdef _CFE_
+#include "cfe_console.h"
+#endif
+
+
+/*----------------------------- Implementation ----------------------------*/
+
+#ifdef DEBUG
+
+static void print_encoded_bytes (u16 s, u16 o);
+static void print_decoded_instruction (void);
+static int parse_line (char *s, int *ps, int *n);
+
+/* should look something like debug's output. */
+void X86EMU_trace_regs (void)
+{
+ if (DEBUG_TRACE()) {
+ x86emu_dump_regs();
+ }
+ if (DEBUG_DECODE() && ! DEBUG_DECODE_NOPRINT()) {
+ printk("%04x:%04x ",M.x86.saved_cs, M.x86.saved_ip);
+ print_encoded_bytes( M.x86.saved_cs, M.x86.saved_ip);
+ print_decoded_instruction();
+ }
+}
+
+void X86EMU_trace_xregs (void)
+{
+ if (DEBUG_TRACE()) {
+ x86emu_dump_xregs();
+ }
+}
+
+void x86emu_just_disassemble (void)
+{
+ /*
+ * This routine called if the flag DEBUG_DISASSEMBLE is set kind
+ * of a hack!
+ */
+ printk("%04x:%04x ",M.x86.saved_cs, M.x86.saved_ip);
+ print_encoded_bytes( M.x86.saved_cs, M.x86.saved_ip);
+ print_decoded_instruction();
+}
+
+static u16 disassemble_forward (u16 seg, u16 off, int n)
+{
+ X86EMU_sysEnv tregs;
+ int i;
+ u8 op1;
+ u16 finaloffset;
+ /*
+ * hack, hack, hack. What we do is use the exact machinery set up
+ * for execution, except that now there is an additional state
+ * flag associated with the "execution", and we are using a copy
+ * of the register struct. All the major opcodes, once fully
+ * decoded, have the following two steps: TRACE_REGS(r,m);
+ * SINGLE_STEP(r,m); which disappear if DEBUG is not defined to
+ * the preprocessor. The TRACE_REGS macro expands to:
+ *
+ * if (debug&DEBUG_DISASSEMBLE)
+ * {just_disassemble(); goto EndOfInstruction;}
+ * if (debug&DEBUG_TRACE) trace_regs(r,m);
+ *
+ * ...... and at the last line of the routine.
+ *
+ * EndOfInstruction: end_instr();
+ *
+ * Up to the point where TRACE_REG is expanded, NO modifications
+ * are done to any register EXCEPT the IP register, for fetch and
+ * decoding purposes.
+ *
+ * This was done for an entirely different reason, but makes a
+ * nice way to get the system to help debug codes.
+ */
+ tregs = M;
+ M.x86.R_IP = off;
+ M.x86.R_CS = seg;
+ M.x86.saved_ip = off;
+ M.x86.saved_cs = seg;
+
+ /* reset the decoding buffers */
+ M.x86.enc_str_pos = 0;
+ M.x86.enc_pos = 0;
+
+ /* turn on the "disassemble only, no execute" flag */
+ M.x86.debug |= DEBUG_DISASSEMBLE_F;
+
+ /* DUMP NEXT n instructions to screen in straight_line fashion */
+ /*
+ * This looks like the regular instruction fetch stream, except
+ * that when this occurs, each fetched opcode, upon seeing the
+ * DEBUG_DISASSEMBLE flag set, exits immediately after decoding
+ * the instruction. XXX --- CHECK THAT MEM IS NOT AFFECTED!!!
+ * Note the use of a copy of the register structure...
+ */
+ for (i=0; i<n; i++) {
+ op1 = (*sys_rdb)(((u32)M.x86.R_CS<<4) + (M.x86.R_IP++));
+ INC_DECODED_INST_LEN(1);
+ (x86emu_optab[op1])(op1);
+ M.x86.saved_ip = M.x86.R_IP;
+ }
+ finaloffset = M.x86.R_IP;
+ M = tregs;
+ /* end major hack mode. */
+ return finaloffset;
+}
+
+void x86emu_check_ip_access (void)
+{
+ /* NULL as of now */
+}
+
+void x86emu_check_sp_access (void)
+{
+}
+
+void x86emu_check_mem_access (u32 dummy)
+{
+ /* check bounds, etc */
+}
+
+void x86emu_check_data_access (uint dummy1, uint dummy2)
+{
+ /* check bounds, etc */
+}
+
+void x86emu_inc_decoded_inst_len (int x)
+{
+ M.x86.enc_pos += x;
+}
+
+void x86emu_decode_printf (char *x)
+{
+ sprintf(M.x86.decoded_buf+M.x86.enc_str_pos,"%s",x);
+ M.x86.enc_str_pos += strlen(x);
+}
+
+void x86emu_decode_printf2 (char *x, int y)
+{
+ char temp[100];
+ sprintf(temp,x,y);
+ sprintf(M.x86.decoded_buf+M.x86.enc_str_pos,"%s",temp);
+ M.x86.enc_str_pos += strlen(temp);
+}
+
+void x86emu_end_instr (void)
+{
+ M.x86.enc_str_pos = 0;
+ M.x86.enc_pos = 0;
+}
+
+static void print_encoded_bytes (u16 s, u16 o)
+{
+ int i;
+ char buf1[64];
+ buf1[0] = 0;
+ for (i=0; i< M.x86.enc_pos; i++) {
+ sprintf(buf1+2*i,"%02x", fetch_data_byte_abs(s,o+i));
+ }
+ printk("%-20s",buf1);
+}
+
+static void print_decoded_instruction (void)
+{
+ printk("%s", M.x86.decoded_buf);
+}
+
+void x86emu_print_int_vect (u16 iv)
+{
+ u16 seg,off;
+
+ if (iv > 256) return;
+ seg = fetch_data_word_abs(0,iv*4);
+ off = fetch_data_word_abs(0,iv*4+2);
+ printk("%04x:%04x ", seg, off);
+}
+
+void X86EMU_dump_memory (u16 seg, u16 off, u32 amt)
+{
+ u32 start = off & 0xfffffff0;
+ u32 end = (off+16) & 0xfffffff0;
+ u32 i;
+ u32 current;
+
+ current = start;
+ while (end <= off + amt) {
+ printk("%04x:%04x ", seg, start);
+ for (i=start; i< off; i++)
+ printk(" ");
+ for ( ; i< end; i++)
+ printk("%02x ", fetch_data_byte_abs(seg,i));
+ printk("\n");
+ start = end;
+ end = start + 16;
+ }
+}
+
+void x86emu_single_step (void)
+{
+ char s[1024];
+ int ps[10];
+ int ntok;
+ int cmd;
+ int done;
+ int segment;
+ int offset;
+ static int breakpoint;
+ static int noDecode = 1;
+
+ char *p;
+
+ if (DEBUG_BREAK()) {
+ if (M.x86.saved_ip != breakpoint) {
+ return;
+ }
+ else {
+ M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
+ M.x86.debug |= DEBUG_TRACE_F;
+ M.x86.debug &= ~DEBUG_BREAK_F;
+ print_decoded_instruction ();
+ X86EMU_trace_regs();
+ }
+ }
+ done=0;
+ offset = M.x86.saved_ip;
+ while (!done) {
+#ifdef _CFE_
+ cmd = console_readline("-",s,1023);
+ if (cmd) { s[cmd] = '\n'; s[cmd+1] = 0;}
+ p = s;
+#else
+ printk("-");
+ p = fgets(s, 1023, stdin);
+#endif
+ cmd = parse_line(s, ps, &ntok);
+ switch(cmd) {
+ case 'u':
+ if (ntok == 2) { offset = ps[1]; }
+ offset = disassemble_forward(M.x86.saved_cs,(u16)offset,10);
+ break;
+ case 'd':
+ if (ntok == 2) {
+ segment = M.x86.saved_cs;
+ offset = ps[1];
+ X86EMU_dump_memory(segment,(u16)offset,16);
+ offset += 16;
+ } else if (ntok == 3) {
+ segment = ps[1];
+ offset = ps[2];
+ X86EMU_dump_memory(segment,(u16)offset,16);
+ offset += 16;
+ } else {
+ segment = M.x86.saved_cs;
+ X86EMU_dump_memory(segment,(u16)offset,16);
+ offset += 16;
+ }
+ break;
+ case 'c':
+ M.x86.debug ^= DEBUG_TRACECALL_F;
+ break;
+ case 's':
+ M.x86.debug ^= DEBUG_SVC_F | DEBUG_SYS_F | DEBUG_SYSINT_F;
+ break;
+ case 'r':
+ X86EMU_trace_regs();
+ break;
+ case 'x':
+ X86EMU_trace_xregs();
+ break;
+ case 'g':
+ if (ntok == 2) {
+ breakpoint = ps[1];
+ if (noDecode) {
+ M.x86.debug |= DEBUG_DECODE_NOPRINT_F;
+ } else {
+ M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
+ }
+ M.x86.debug &= ~DEBUG_TRACE_F;
+ M.x86.debug |= DEBUG_BREAK_F;
+ done = 1;
+ }
+ break;
+ case 'q':
+ M.x86.debug &= ~DEBUG_TRACE_F;
+ M.x86.debug &= ~DEBUG_BREAK_F;
+ M.x86.debug &= ~DEBUG_STEP_F;
+ M.x86.debug &= ~DEBUG_DECODE_F;
+ done = 1;
+ break;
+ case 'P':
+ noDecode = (noDecode)?0:1;
+ printk("Toggled decoding to %s\n",(noDecode)?"FALSE":"TRUE");
+ break;
+ case 't':
+ case 0:
+ done = 1;
+ break;
+ }
+ }
+}
+
+int X86EMU_trace_on(void)
+{
+ return M.x86.debug |= DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F;
+}
+
+int X86EMU_trace_off(void)
+{
+ return M.x86.debug &= ~(DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F);
+}
+
+static int parse_line (char *s, int *ps, int *n)
+{
+ int cmd;
+
+ *n = 0;
+ while(*s == ' ' || *s == '\t') s++;
+ ps[*n] = *s;
+ switch (*s) {
+ case '\n':
+ *n += 1;
+ return 0;
+ default:
+ cmd = *s;
+ *n += 1;
+ }
+
+ while (1) {
+ while (*s != ' ' && *s != '\t' && *s != '\n') s++;
+
+ if (*s == '\n')
+ return cmd;
+
+ while(*s == ' ' || *s == '\t') s++;
+#ifdef _CFE_
+ ps[*n] = xtoi(s);
+#else
+ sscanf(s,"%x",&ps[*n]);
+#endif
+ *n += 1;
+ }
+}
+
+#endif /* DEBUG */
+
+void x86emu_dump_regs (void)
+{
+ printk("\tAX=%04x ", M.x86.R_AX );
+ printk("BX=%04x ", M.x86.R_BX );
+ printk("CX=%04x ", M.x86.R_CX );
+ printk("DX=%04x ", M.x86.R_DX );
+ printk("SP=%04x ", M.x86.R_SP );
+ printk("BP=%04x ", M.x86.R_BP );
+ printk("SI=%04x ", M.x86.R_SI );
+ printk("DI=%04x\n", M.x86.R_DI );
+ printk("\tDS=%04x ", M.x86.R_DS );
+ printk("ES=%04x ", M.x86.R_ES );
+ printk("SS=%04x ", M.x86.R_SS );
+ printk("CS=%04x ", M.x86.R_CS );
+ printk("IP=%04x ", M.x86.R_IP );
+ if (ACCESS_FLAG(F_OF)) printk("OV "); /* CHECKED... */
+ else printk("NV ");
+ if (ACCESS_FLAG(F_DF)) printk("DN ");
+ else printk("UP ");
+ if (ACCESS_FLAG(F_IF)) printk("EI ");
+ else printk("DI ");
+ if (ACCESS_FLAG(F_SF)) printk("NG ");
+ else printk("PL ");
+ if (ACCESS_FLAG(F_ZF)) printk("ZR ");
+ else printk("NZ ");
+ if (ACCESS_FLAG(F_AF)) printk("AC ");
+ else printk("NA ");
+ if (ACCESS_FLAG(F_PF)) printk("PE ");
+ else printk("PO ");
+ if (ACCESS_FLAG(F_CF)) printk("CY ");
+ else printk("NC ");
+ printk("\n");
+}
+
+void x86emu_dump_xregs (void)
+{
+ printk("\tEAX=%08x ", M.x86.R_EAX );
+ printk("EBX=%08x ", M.x86.R_EBX );
+ printk("ECX=%08x ", M.x86.R_ECX );
+ printk("EDX=%08x \n", M.x86.R_EDX );
+ printk("\tESP=%08x ", M.x86.R_ESP );
+ printk("EBP=%08x ", M.x86.R_EBP );
+ printk("ESI=%08x ", M.x86.R_ESI );
+ printk("EDI=%08x\n", M.x86.R_EDI );
+ printk("\tDS=%04x ", M.x86.R_DS );
+ printk("ES=%04x ", M.x86.R_ES );
+ printk("SS=%04x ", M.x86.R_SS );
+ printk("CS=%04x ", M.x86.R_CS );
+ printk("EIP=%08x\n\t", M.x86.R_EIP );
+ if (ACCESS_FLAG(F_OF)) printk("OV "); /* CHECKED... */
+ else printk("NV ");
+ if (ACCESS_FLAG(F_DF)) printk("DN ");
+ else printk("UP ");
+ if (ACCESS_FLAG(F_IF)) printk("EI ");
+ else printk("DI ");
+ if (ACCESS_FLAG(F_SF)) printk("NG ");
+ else printk("PL ");
+ if (ACCESS_FLAG(F_ZF)) printk("ZR ");
+ else printk("NZ ");
+ if (ACCESS_FLAG(F_AF)) printk("AC ");
+ else printk("NA ");
+ if (ACCESS_FLAG(F_PF)) printk("PE ");
+ else printk("PO ");
+ if (ACCESS_FLAG(F_CF)) printk("CY ");
+ else printk("NC ");
+ printk("\n");
+}
diff --git a/cfe/cfe/x86emu/decode.c b/cfe/cfe/x86emu/decode.c
new file mode 100644
index 0000000..10082eb
--- /dev/null
+++ b/cfe/cfe/x86emu/decode.c
@@ -0,0 +1,1000 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: This file includes subroutines which are related to
+* instruction decoding and accessess of immediate data via IP. etc.
+*
+****************************************************************************/
+
+/* $XFree86: xc/extras/x86emu/src/x86emu/decode.c,v 1.8 2000/12/13 03:19:34 tsi Exp $ */
+
+#include "x86emu/x86emui.h"
+#include "cfe_console.h"
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+REMARKS:
+Handles any pending asychronous interrupts.
+****************************************************************************/
+static void x86emu_intr_handle(void)
+{
+ u8 intno;
+
+ if (M.x86.intr & INTR_SYNCH) {
+ intno = M.x86.intno;
+ if (_X86EMU_intrTab[intno]) {
+ (*_X86EMU_intrTab[intno])(intno);
+ } else {
+ push_word((u16)M.x86.R_FLG);
+ CLEAR_FLAG(F_IF);
+ CLEAR_FLAG(F_TF);
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = mem_access_word(intno * 4 + 2);
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = mem_access_word(intno * 4);
+ M.x86.intr = 0;
+ }
+ }
+}
+
+/****************************************************************************
+PARAMETERS:
+intrnum - Interrupt number to raise
+
+REMARKS:
+Raise the specified interrupt to be handled before the execution of the
+next instruction.
+****************************************************************************/
+void x86emu_intr_raise(
+ u8 intrnum)
+{
+ M.x86.intno = intrnum;
+ M.x86.intr |= INTR_SYNCH;
+}
+
+#ifdef DEBUG
+extern u8 inb(u32);
+#endif
+
+/****************************************************************************
+REMARKS:
+Main execution loop for the emulator. We return from here when the system
+halts, which is normally caused by a stack fault when we return from the
+original real mode call.
+****************************************************************************/
+void X86EMU_exec(void)
+{
+ u8 op1;
+
+ M.x86.intr = 0;
+ DB(x86emu_end_instr();)
+
+ for (;;) {
+DB( if (CHECK_IP_FETCH())
+ x86emu_check_ip_access();)
+ /* If debugging, save the IP and CS values. */
+ SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP);
+ INC_DECODED_INST_LEN(1);
+ if (M.x86.intr) {
+ if (M.x86.intr & INTR_HALTED) {
+DB( printk("halted\n");
+ X86EMU_trace_regs();)
+ return;
+ }
+ if (((M.x86.intr & INTR_SYNCH) && (M.x86.intno == 0 || M.x86.intno == 2)) ||
+ !ACCESS_FLAG(F_IF)) {
+ x86emu_intr_handle();
+ }
+ }
+#ifdef DEBUG
+ if (inb(0x3f8 + 5) & 1) {
+ M.x86.debug |= DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F;
+ }
+#endif
+ op1 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
+ (*x86emu_optab[op1])(op1);
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Halts the system by setting the halted system flag.
+****************************************************************************/
+void X86EMU_halt_sys(void)
+{
+ M.x86.intr |= INTR_HALTED;
+}
+
+/****************************************************************************
+PARAMETERS:
+mod - Mod value from decoded byte
+regh - Reg h value from decoded byte
+regl - Reg l value from decoded byte
+
+REMARKS:
+Raise the specified interrupt to be handled before the execution of the
+next instruction.
+
+NOTE: Do not inline this function, as (*sys_rdb) is already inline!
+****************************************************************************/
+void fetch_decode_modrm(
+ int *mod,
+ int *regh,
+ int *regl)
+{
+ int fetched;
+
+DB( if (CHECK_IP_FETCH())
+ x86emu_check_ip_access();)
+ fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
+ INC_DECODED_INST_LEN(1);
+ *mod = (fetched >> 6) & 0x03;
+ *regh = (fetched >> 3) & 0x07;
+ *regl = (fetched >> 0) & 0x07;
+}
+
+/****************************************************************************
+RETURNS:
+Immediate byte value read from instruction queue
+
+REMARKS:
+This function returns the immediate byte from the instruction queue, and
+moves the instruction pointer to the next value.
+
+NOTE: Do not inline this function, as (*sys_rdb) is already inline!
+****************************************************************************/
+u8 fetch_byte_imm(void)
+{
+ u8 fetched;
+
+DB( if (CHECK_IP_FETCH())
+ x86emu_check_ip_access();)
+ fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
+ INC_DECODED_INST_LEN(1);
+ return fetched;
+}
+
+/****************************************************************************
+RETURNS:
+Immediate word value read from instruction queue
+
+REMARKS:
+This function returns the immediate byte from the instruction queue, and
+moves the instruction pointer to the next value.
+
+NOTE: Do not inline this function, as (*sys_rdw) is already inline!
+****************************************************************************/
+u16 fetch_word_imm(void)
+{
+ u16 fetched;
+
+DB( if (CHECK_IP_FETCH())
+ x86emu_check_ip_access();)
+ fetched = (*sys_rdw)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
+ M.x86.R_IP += 2;
+ INC_DECODED_INST_LEN(2);
+ return fetched;
+}
+
+/****************************************************************************
+RETURNS:
+Immediate lone value read from instruction queue
+
+REMARKS:
+This function returns the immediate byte from the instruction queue, and
+moves the instruction pointer to the next value.
+
+NOTE: Do not inline this function, as (*sys_rdw) is already inline!
+****************************************************************************/
+u32 fetch_long_imm(void)
+{
+ u32 fetched;
+
+DB( if (CHECK_IP_FETCH())
+ x86emu_check_ip_access();)
+ fetched = (*sys_rdl)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
+ M.x86.R_IP += 4;
+ INC_DECODED_INST_LEN(4);
+ return fetched;
+}
+
+/****************************************************************************
+RETURNS:
+Value of the default data segment
+
+REMARKS:
+Inline function that returns the default data segment for the current
+instruction.
+
+On the x86 processor, the default segment is not always DS if there is
+no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
+addresses relative to SS (ie: on the stack). So, at the minimum, all
+decodings of addressing modes would have to set/clear a bit describing
+whether the access is relative to DS or SS. That is the function of the
+cpu-state-varible M.x86.mode. There are several potential states:
+
+ repe prefix seen (handled elsewhere)
+ repne prefix seen (ditto)
+
+ cs segment override
+ ds segment override
+ es segment override
+ fs segment override
+ gs segment override
+ ss segment override
+
+ ds/ss select (in absense of override)
+
+Each of the above 7 items are handled with a bit in the mode field.
+****************************************************************************/
+_INLINE u32 get_data_segment(void)
+{
+#define GET_SEGMENT(segment)
+ switch (M.x86.mode & SYSMODE_SEGMASK) {
+ case 0: /* default case: use ds register */
+ case SYSMODE_SEGOVR_DS:
+ case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
+ return M.x86.R_DS;
+ case SYSMODE_SEG_DS_SS: /* non-overridden, use ss register */
+ return M.x86.R_SS;
+ case SYSMODE_SEGOVR_CS:
+ case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
+ return M.x86.R_CS;
+ case SYSMODE_SEGOVR_ES:
+ case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
+ return M.x86.R_ES;
+ case SYSMODE_SEGOVR_FS:
+ case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
+ return M.x86.R_FS;
+ case SYSMODE_SEGOVR_GS:
+ case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
+ return M.x86.R_GS;
+ case SYSMODE_SEGOVR_SS:
+ case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
+ return M.x86.R_SS;
+ default:
+#ifdef DEBUG
+ printk("error: should not happen: multiple overrides.\n");
+#endif
+ HALT_SYS();
+ return 0;
+ }
+}
+
+/****************************************************************************
+PARAMETERS:
+offset - Offset to load data from
+
+RETURNS:
+Byte value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u8 fetch_data_byte(
+ uint offset)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+ return (*sys_rdb)((get_data_segment() << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+offset - Offset to load data from
+
+RETURNS:
+Word value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u16 fetch_data_word(
+ uint offset)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+ return (*sys_rdw)((get_data_segment() << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+offset - Offset to load data from
+
+RETURNS:
+Long value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u32 fetch_data_long(
+ uint offset)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+ return (*sys_rdl)((get_data_segment() << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to load data from
+offset - Offset to load data from
+
+RETURNS:
+Byte value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u8 fetch_data_byte_abs(
+ uint segment,
+ uint offset)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access(segment, offset);
+#endif
+ return (*sys_rdb)(((u32)segment << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to load data from
+offset - Offset to load data from
+
+RETURNS:
+Word value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u16 fetch_data_word_abs(
+ uint segment,
+ uint offset)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access(segment, offset);
+#endif
+ return (*sys_rdw)(((u32)segment << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to load data from
+offset - Offset to load data from
+
+RETURNS:
+Long value read from the absolute memory location.
+
+NOTE: Do not inline this function as (*sys_rdX) is already inline!
+****************************************************************************/
+u32 fetch_data_long_abs(
+ uint segment,
+ uint offset)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access(segment, offset);
+#endif
+ return (*sys_rdl)(((u32)segment << 4) + offset);
+}
+
+/****************************************************************************
+PARAMETERS:
+offset - Offset to store data at
+val - Value to store
+
+REMARKS:
+Writes a word value to an segmented memory location. The segment used is
+the current 'default' segment, which may have been overridden.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_byte(
+ uint offset,
+ u8 val)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+ (*sys_wrb)((get_data_segment() << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+offset - Offset to store data at
+val - Value to store
+
+REMARKS:
+Writes a word value to an segmented memory location. The segment used is
+the current 'default' segment, which may have been overridden.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_word(
+ uint offset,
+ u16 val)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+ (*sys_wrw)((get_data_segment() << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+offset - Offset to store data at
+val - Value to store
+
+REMARKS:
+Writes a long value to an segmented memory location. The segment used is
+the current 'default' segment, which may have been overridden.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_long(
+ uint offset,
+ u32 val)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access((u16)get_data_segment(), offset);
+#endif
+ (*sys_wrl)((get_data_segment() << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to store data at
+offset - Offset to store data at
+val - Value to store
+
+REMARKS:
+Writes a byte value to an absolute memory location.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_byte_abs(
+ uint segment,
+ uint offset,
+ u8 val)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access(segment, offset);
+#endif
+ (*sys_wrb)(((u32)segment << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to store data at
+offset - Offset to store data at
+val - Value to store
+
+REMARKS:
+Writes a word value to an absolute memory location.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_word_abs(
+ uint segment,
+ uint offset,
+ u16 val)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access(segment, offset);
+#endif
+ (*sys_wrw)(((u32)segment << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+segment - Segment to store data at
+offset - Offset to store data at
+val - Value to store
+
+REMARKS:
+Writes a long value to an absolute memory location.
+
+NOTE: Do not inline this function as (*sys_wrX) is already inline!
+****************************************************************************/
+void store_data_long_abs(
+ uint segment,
+ uint offset,
+ u32 val)
+{
+#ifdef DEBUG
+ if (CHECK_DATA_ACCESS())
+ x86emu_check_data_access(segment, offset);
+#endif
+ (*sys_wrl)(((u32)segment << 4) + offset, val);
+}
+
+/****************************************************************************
+PARAMETERS:
+reg - Register to decode
+
+RETURNS:
+Pointer to the appropriate register
+
+REMARKS:
+Return a pointer to the register given by the R/RM field of the
+modrm byte, for byte operands. Also enables the decoding of instructions.
+****************************************************************************/
+u8* decode_rm_byte_register(
+ int reg)
+{
+ switch (reg) {
+ case 0:
+ DECODE_PRINTF("AL");
+ return &M.x86.R_AL;
+ case 1:
+ DECODE_PRINTF("CL");
+ return &M.x86.R_CL;
+ case 2:
+ DECODE_PRINTF("DL");
+ return &M.x86.R_DL;
+ case 3:
+ DECODE_PRINTF("BL");
+ return &M.x86.R_BL;
+ case 4:
+ DECODE_PRINTF("AH");
+ return &M.x86.R_AH;
+ case 5:
+ DECODE_PRINTF("CH");
+ return &M.x86.R_CH;
+ case 6:
+ DECODE_PRINTF("DH");
+ return &M.x86.R_DH;
+ case 7:
+ DECODE_PRINTF("BH");
+ return &M.x86.R_BH;
+ }
+ HALT_SYS();
+ return NULL; /* NOT REACHED OR REACHED ON ERROR */
+}
+
+/****************************************************************************
+PARAMETERS:
+reg - Register to decode
+
+RETURNS:
+Pointer to the appropriate register
+
+REMARKS:
+Return a pointer to the register given by the R/RM field of the
+modrm byte, for word operands. Also enables the decoding of instructions.
+****************************************************************************/
+u16* decode_rm_word_register(
+ int reg)
+{
+ switch (reg) {
+ case 0:
+ DECODE_PRINTF("AX");
+ return &M.x86.R_AX;
+ case 1:
+ DECODE_PRINTF("CX");
+ return &M.x86.R_CX;
+ case 2:
+ DECODE_PRINTF("DX");
+ return &M.x86.R_DX;
+ case 3:
+ DECODE_PRINTF("BX");
+ return &M.x86.R_BX;
+ case 4:
+ DECODE_PRINTF("SP");
+ return &M.x86.R_SP;
+ case 5:
+ DECODE_PRINTF("BP");
+ return &M.x86.R_BP;
+ case 6:
+ DECODE_PRINTF("SI");
+ return &M.x86.R_SI;
+ case 7:
+ DECODE_PRINTF("DI");
+ return &M.x86.R_DI;
+ }
+ HALT_SYS();
+ return NULL; /* NOTREACHED OR REACHED ON ERROR */
+}
+
+/****************************************************************************
+PARAMETERS:
+reg - Register to decode
+
+RETURNS:
+Pointer to the appropriate register
+
+REMARKS:
+Return a pointer to the register given by the R/RM field of the
+modrm byte, for dword operands. Also enables the decoding of instructions.
+****************************************************************************/
+u32* decode_rm_long_register(
+ int reg)
+{
+ switch (reg) {
+ case 0:
+ DECODE_PRINTF("EAX");
+ return &M.x86.R_EAX;
+ case 1:
+ DECODE_PRINTF("ECX");
+ return &M.x86.R_ECX;
+ case 2:
+ DECODE_PRINTF("EDX");
+ return &M.x86.R_EDX;
+ case 3:
+ DECODE_PRINTF("EBX");
+ return &M.x86.R_EBX;
+ case 4:
+ DECODE_PRINTF("ESP");
+ return &M.x86.R_ESP;
+ case 5:
+ DECODE_PRINTF("EBP");
+ return &M.x86.R_EBP;
+ case 6:
+ DECODE_PRINTF("ESI");
+ return &M.x86.R_ESI;
+ case 7:
+ DECODE_PRINTF("EDI");
+ return &M.x86.R_EDI;
+ }
+ HALT_SYS();
+ return NULL; /* NOTREACHED OR REACHED ON ERROR */
+}
+
+/****************************************************************************
+PARAMETERS:
+reg - Register to decode
+
+RETURNS:
+Pointer to the appropriate register
+
+REMARKS:
+Return a pointer to the register given by the R/RM field of the
+modrm byte, for word operands, modified from above for the weirdo
+special case of segreg operands. Also enables the decoding of instructions.
+****************************************************************************/
+u16* decode_rm_seg_register(
+ int reg)
+{
+ switch (reg) {
+ case 0:
+ DECODE_PRINTF("ES");
+ return &M.x86.R_ES;
+ case 1:
+ DECODE_PRINTF("CS");
+ return &M.x86.R_CS;
+ case 2:
+ DECODE_PRINTF("SS");
+ return &M.x86.R_SS;
+ case 3:
+ DECODE_PRINTF("DS");
+ return &M.x86.R_DS;
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ DECODE_PRINTF("ILLEGAL SEGREG");
+ break;
+ }
+ HALT_SYS();
+ return NULL; /* NOT REACHED OR REACHED ON ERROR */
+}
+
+
+/****************************************************************************
+PARAMETERS:
+sib - SIB value to decode
+
+RETURNS:
+Offset in memory for the address decoding
+
+REMARKS:
+Return the offset given by the specified SIB byte.
+
+NOTE: The code which specifies the corresponding segment (ds vs ss)
+ below in the case of [BP+..]. The assumption here is that at the
+ point that this subroutine is called, the bit corresponding to
+ SYSMODE_SEG_DS_SS will be zero. After every instruction
+ except the segment override instructions, this bit (as well
+ as any bits indicating segment overrides) will be clear. So
+ if a SS access is needed, set this bit. Otherwise, DS access
+ occurs (unless any of the segment override bits are set).
+****************************************************************************/
+static unsigned decode_sib_address(
+ int sib)
+{
+ unsigned ss,index,base;
+ unsigned addr = 0;
+
+ ss = (sib >> 6) & 3;
+ index = (sib >> 3) & 7;
+ base = (sib & 7);
+
+ switch (base) {
+ case 0:
+ DECODE_PRINTF("[EAX");
+ addr = M.x86.R_EAX;
+ break;
+ case 1:
+ DECODE_PRINTF("[ECX");
+ addr = M.x86.R_ECX;
+ break;
+ case 2:
+ DECODE_PRINTF("[EDX");
+ addr = M.x86.R_EDX;
+ break;
+ case 3:
+ DECODE_PRINTF("[EBX");
+ addr = M.x86.R_EBX;
+ break;
+ case 4:
+ DECODE_PRINTF("[ESP");
+ addr = M.x86.R_ESP;
+ break;
+ case 5:
+ DECODE_PRINTF("[invalid");
+ addr = M.x86.R_ESP;/* incorrect */
+ break;
+ case 6:
+ DECODE_PRINTF("[invalid");
+ addr = M.x86.R_ESP;/* incorrect */
+ break;
+ case 7:
+ DECODE_PRINTF("[invalid");
+ addr = M.x86.R_ESP; /* incorrect */
+ break;
+ }
+
+ switch (index) {
+ case 0:
+ DECODE_PRINTF("+EAX");
+ addr += M.x86.R_EAX*(1<<ss);
+ break;
+ case 1:
+ DECODE_PRINTF("+ECX");
+ addr += M.x86.R_ECX*(1<<ss);
+ break;
+ case 2:
+ DECODE_PRINTF("+EDX");
+ addr += M.x86.R_EDX*(1<<ss);
+ break;
+ case 3:
+ DECODE_PRINTF("+EBX");
+ addr += M.x86.R_EBX*(1<<ss);
+ break;
+ case 4:
+ break;
+ case 5:
+ DECODE_PRINTF("+EBP");
+ addr += M.x86.R_EBP*(1<<ss);
+ break;
+ case 6:
+ DECODE_PRINTF("+ESI");
+ addr += M.x86.R_ESI*(1<<ss);
+ break;
+ case 7:
+ DECODE_PRINTF("+EDI");
+ addr += M.x86.R_EDI*(1<<ss);
+ break;
+ }
+
+ switch (ss) {
+ case 0:
+ DECODE_PRINTF("]");
+ break;
+ case 1:
+ DECODE_PRINTF("*2]");
+ break;
+ case 2:
+ DECODE_PRINTF("*4]");
+ break;
+ case 3:
+ DECODE_PRINTF("*8]");
+ break;
+ }
+
+ return addr;
+
+}
+
+/****************************************************************************
+PARAMETERS:
+rm - RM value to decode
+
+RETURNS:
+Offset in memory for the address decoding
+
+REMARKS:
+Return the offset given by mod=00 addressing. Also enables the
+decoding of instructions.
+
+NOTE: The code which specifies the corresponding segment (ds vs ss)
+ below in the case of [BP+..]. The assumption here is that at the
+ point that this subroutine is called, the bit corresponding to
+ SYSMODE_SEG_DS_SS will be zero. After every instruction
+ except the segment override instructions, this bit (as well
+ as any bits indicating segment overrides) will be clear. So
+ if a SS access is needed, set this bit. Otherwise, DS access
+ occurs (unless any of the segment override bits are set).
+****************************************************************************/
+unsigned decode_rm00_address(
+ int rm)
+{
+ unsigned offset;
+
+ switch (rm) {
+ case 0:
+ DECODE_PRINTF("[BX+SI]");
+ return M.x86.R_BX + M.x86.R_SI;
+ case 1:
+ DECODE_PRINTF("[BX+DI]");
+ return M.x86.R_BX + M.x86.R_DI;
+ case 2:
+ DECODE_PRINTF("[BP+SI]");
+ M.x86.mode |= SYSMODE_SEG_DS_SS;
+ return M.x86.R_BP + M.x86.R_SI;
+ case 3:
+ DECODE_PRINTF("[BP+DI]");
+ M.x86.mode |= SYSMODE_SEG_DS_SS;
+ return M.x86.R_BP + M.x86.R_DI;
+ case 4:
+ /* If SYSMODE_PREFIX_ADDR is set, get the SIB byte */
+ if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
+ unsigned sib;
+ sib = fetch_byte_imm();
+ return decode_sib_address(sib);
+ }
+ else {
+ DECODE_PRINTF("[SI]");
+ return M.x86.R_SI;
+ }
+ case 5:
+ DECODE_PRINTF("[DI]");
+ return M.x86.R_DI;
+ case 6:
+ offset = fetch_word_imm();
+ DECODE_PRINTF2("[%04x]", offset);
+ return offset;
+ case 7:
+ DECODE_PRINTF("[BX]");
+ return M.x86.R_BX;
+ }
+ HALT_SYS();
+ return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+rm - RM value to decode
+
+RETURNS:
+Offset in memory for the address decoding
+
+REMARKS:
+Return the offset given by mod=01 addressing. Also enables the
+decoding of instructions.
+****************************************************************************/
+unsigned decode_rm01_address(
+ int rm)
+{
+ int displacement = (s8)fetch_byte_imm();
+ switch (rm) {
+ case 0:
+ DECODE_PRINTF2("%d[BX+SI]", displacement);
+ return M.x86.R_BX + M.x86.R_SI + displacement;
+ case 1:
+ DECODE_PRINTF2("%d[BX+DI]", displacement);
+ return M.x86.R_BX + M.x86.R_DI + displacement;
+ case 2:
+ DECODE_PRINTF2("%d[BP+SI]", displacement);
+ M.x86.mode |= SYSMODE_SEG_DS_SS;
+ return M.x86.R_BP + M.x86.R_SI + displacement;
+ case 3:
+ DECODE_PRINTF2("%d[BP+DI]", displacement);
+ M.x86.mode |= SYSMODE_SEG_DS_SS;
+ return M.x86.R_BP + M.x86.R_DI + displacement;
+ case 4:
+ DECODE_PRINTF2("%d[SI]", displacement);
+ return M.x86.R_SI + displacement;
+ case 5:
+ DECODE_PRINTF2("%d[DI]", displacement);
+ return M.x86.R_DI + displacement;
+ case 6:
+ DECODE_PRINTF2("%d[BP]", displacement);
+ M.x86.mode |= SYSMODE_SEG_DS_SS;
+ return M.x86.R_BP + displacement;
+ case 7:
+ DECODE_PRINTF2("%d[BX]", displacement);
+ return M.x86.R_BX + displacement;
+ }
+ HALT_SYS();
+ return 0; /* SHOULD NOT HAPPEN */
+}
+
+/****************************************************************************
+PARAMETERS:
+rm - RM value to decode
+
+RETURNS:
+Offset in memory for the address decoding
+
+REMARKS:
+Return the offset given by mod=10 addressing. Also enables the
+decoding of instructions.
+****************************************************************************/
+unsigned decode_rm10_address(
+ int rm)
+{
+ unsigned displacement = (u16)fetch_word_imm();
+ switch (rm) {
+ case 0:
+ DECODE_PRINTF2("%d[BX+SI]", displacement);
+ return M.x86.R_BX + M.x86.R_SI + displacement;
+ case 1:
+ DECODE_PRINTF2("%d[BX+DI]", displacement);
+ return M.x86.R_BX + M.x86.R_DI + displacement;
+ case 2:
+ DECODE_PRINTF2("%d[BP+SI]", displacement);
+ M.x86.mode |= SYSMODE_SEG_DS_SS;
+ return M.x86.R_BP + M.x86.R_SI + displacement;
+ case 3:
+ DECODE_PRINTF2("%d[BP+DI]", displacement);
+ M.x86.mode |= SYSMODE_SEG_DS_SS;
+ return M.x86.R_BP + M.x86.R_DI + displacement;
+ case 4:
+ DECODE_PRINTF2("%d[SI]", displacement);
+ return M.x86.R_SI + displacement;
+ case 5:
+ DECODE_PRINTF2("%d[DI]", displacement);
+ return M.x86.R_DI + displacement;
+ case 6:
+ DECODE_PRINTF2("%d[BP]", displacement);
+ M.x86.mode |= SYSMODE_SEG_DS_SS;
+ return M.x86.R_BP + displacement;
+ case 7:
+ DECODE_PRINTF2("%d[BX]", displacement);
+ return M.x86.R_BX + displacement;
+ }
+ HALT_SYS();
+ return 0;
+ /*NOTREACHED */
+}
diff --git a/cfe/cfe/x86emu/fpu.c b/cfe/cfe/x86emu/fpu.c
new file mode 100644
index 0000000..08aea42
--- /dev/null
+++ b/cfe/cfe/x86emu/fpu.c
@@ -0,0 +1,945 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: This file contains the code to implement the decoding and
+* emulation of the FPU instructions.
+*
+****************************************************************************/
+
+#include "x86emu/x86emui.h"
+
+/*----------------------------- Implementation ----------------------------*/
+
+/* opcode=0xd8 */
+void x86emuOp_esc_coprocess_d8(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("ESC D8\n");
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef DEBUG
+
+static char *x86emu_fpu_op_d9_tab[] = {
+ "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
+ "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
+
+ "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
+ "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
+
+ "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
+ "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
+};
+
+static char *x86emu_fpu_op_d9_tab1[] = {
+ "FLD\t", "FLD\t", "FLD\t", "FLD\t",
+ "FLD\t", "FLD\t", "FLD\t", "FLD\t",
+
+ "FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t",
+ "FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t",
+
+ "FNOP", "ESC_D9", "ESC_D9", "ESC_D9",
+ "ESC_D9", "ESC_D9", "ESC_D9", "ESC_D9",
+
+ "FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t",
+ "FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t",
+
+ "FCHS", "FABS", "ESC_D9", "ESC_D9",
+ "FTST", "FXAM", "ESC_D9", "ESC_D9",
+
+ "FLD1", "FLDL2T", "FLDL2E", "FLDPI",
+ "FLDLG2", "FLDLN2", "FLDZ", "ESC_D9",
+
+ "F2XM1", "FYL2X", "FPTAN", "FPATAN",
+ "FXTRACT", "ESC_D9", "FDECSTP", "FINCSTP",
+
+ "FPREM", "FYL2XP1", "FSQRT", "ESC_D9",
+ "FRNDINT", "FSCALE", "ESC_D9", "ESC_D9",
+};
+
+#endif /* DEBUG */
+
+/* opcode=0xd9 */
+void x86emuOp_esc_coprocess_d9(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 stkelem;
+
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (mod != 3) {
+ DECODE_PRINTINSTR32(x86emu_fpu_op_d9_tab, mod, rh, rl);
+ } else {
+ DECODE_PRINTF(x86emu_fpu_op_d9_tab1[(rh << 3) + rl]);
+ }
+#endif
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 3: /* register to register */
+ stkelem = (u8)rl;
+ if (rh < 4) {
+ DECODE_PRINTF2("ST(%d)\n", stkelem);
+ } else {
+ DECODE_PRINTF("\n");
+ }
+ break;
+ }
+#ifdef X86EMU_FPU_PRESENT
+ /* execute */
+ switch (mod) {
+ case 3:
+ switch (rh) {
+ case 0:
+ x86emu_fpu_R_fld(X86EMU_FPU_STKTOP, stkelem);
+ break;
+ case 1:
+ x86emu_fpu_R_fxch(X86EMU_FPU_STKTOP, stkelem);
+ break;
+ case 2:
+ switch (rl) {
+ case 0:
+ x86emu_fpu_R_nop();
+ break;
+ default:
+ x86emu_fpu_illegal();
+ break;
+ }
+ case 3:
+ x86emu_fpu_R_fstp(X86EMU_FPU_STKTOP, stkelem);
+ break;
+ case 4:
+ switch (rl) {
+ case 0:
+ x86emu_fpu_R_fchs(X86EMU_FPU_STKTOP);
+ break;
+ case 1:
+ x86emu_fpu_R_fabs(X86EMU_FPU_STKTOP);
+ break;
+ case 4:
+ x86emu_fpu_R_ftst(X86EMU_FPU_STKTOP);
+ break;
+ case 5:
+ x86emu_fpu_R_fxam(X86EMU_FPU_STKTOP);
+ break;
+ default:
+ /* 2,3,6,7 */
+ x86emu_fpu_illegal();
+ break;
+ }
+ break;
+
+ case 5:
+ switch (rl) {
+ case 0:
+ x86emu_fpu_R_fld1(X86EMU_FPU_STKTOP);
+ break;
+ case 1:
+ x86emu_fpu_R_fldl2t(X86EMU_FPU_STKTOP);
+ break;
+ case 2:
+ x86emu_fpu_R_fldl2e(X86EMU_FPU_STKTOP);
+ break;
+ case 3:
+ x86emu_fpu_R_fldpi(X86EMU_FPU_STKTOP);
+ break;
+ case 4:
+ x86emu_fpu_R_fldlg2(X86EMU_FPU_STKTOP);
+ break;
+ case 5:
+ x86emu_fpu_R_fldln2(X86EMU_FPU_STKTOP);
+ break;
+ case 6:
+ x86emu_fpu_R_fldz(X86EMU_FPU_STKTOP);
+ break;
+ default:
+ /* 7 */
+ x86emu_fpu_illegal();
+ break;
+ }
+ break;
+
+ case 6:
+ switch (rl) {
+ case 0:
+ x86emu_fpu_R_f2xm1(X86EMU_FPU_STKTOP);
+ break;
+ case 1:
+ x86emu_fpu_R_fyl2x(X86EMU_FPU_STKTOP);
+ break;
+ case 2:
+ x86emu_fpu_R_fptan(X86EMU_FPU_STKTOP);
+ break;
+ case 3:
+ x86emu_fpu_R_fpatan(X86EMU_FPU_STKTOP);
+ break;
+ case 4:
+ x86emu_fpu_R_fxtract(X86EMU_FPU_STKTOP);
+ break;
+ case 5:
+ x86emu_fpu_illegal();
+ break;
+ case 6:
+ x86emu_fpu_R_decstp();
+ break;
+ case 7:
+ x86emu_fpu_R_incstp();
+ break;
+ }
+ break;
+
+ case 7:
+ switch (rl) {
+ case 0:
+ x86emu_fpu_R_fprem(X86EMU_FPU_STKTOP);
+ break;
+ case 1:
+ x86emu_fpu_R_fyl2xp1(X86EMU_FPU_STKTOP);
+ break;
+ case 2:
+ x86emu_fpu_R_fsqrt(X86EMU_FPU_STKTOP);
+ break;
+ case 3:
+ x86emu_fpu_illegal();
+ break;
+ case 4:
+ x86emu_fpu_R_frndint(X86EMU_FPU_STKTOP);
+ break;
+ case 5:
+ x86emu_fpu_R_fscale(X86EMU_FPU_STKTOP);
+ break;
+ case 6:
+ case 7:
+ default:
+ x86emu_fpu_illegal();
+ break;
+ }
+ break;
+
+ default:
+ switch (rh) {
+ case 0:
+ x86emu_fpu_M_fld(X86EMU_FPU_FLOAT, destoffset);
+ break;
+ case 1:
+ x86emu_fpu_illegal();
+ break;
+ case 2:
+ x86emu_fpu_M_fst(X86EMU_FPU_FLOAT, destoffset);
+ break;
+ case 3:
+ x86emu_fpu_M_fstp(X86EMU_FPU_FLOAT, destoffset);
+ break;
+ case 4:
+ x86emu_fpu_M_fldenv(X86EMU_FPU_WORD, destoffset);
+ break;
+ case 5:
+ x86emu_fpu_M_fldcw(X86EMU_FPU_WORD, destoffset);
+ break;
+ case 6:
+ x86emu_fpu_M_fstenv(X86EMU_FPU_WORD, destoffset);
+ break;
+ case 7:
+ x86emu_fpu_M_fstcw(X86EMU_FPU_WORD, destoffset);
+ break;
+ }
+ }
+ }
+#endif /* X86EMU_FPU_PRESENT */
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef DEBUG
+
+char *x86emu_fpu_op_da_tab[] = {
+ "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
+ "FICOMP\tDWORD PTR ",
+ "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
+ "FIDIVR\tDWORD PTR ",
+
+ "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
+ "FICOMP\tDWORD PTR ",
+ "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
+ "FIDIVR\tDWORD PTR ",
+
+ "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
+ "FICOMP\tDWORD PTR ",
+ "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
+ "FIDIVR\tDWORD PTR ",
+
+ "ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ",
+ "ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ",
+};
+
+#endif /* DEBUG */
+
+/* opcode=0xda */
+void x86emuOp_esc_coprocess_da(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 stkelem;
+
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ DECODE_PRINTINSTR32(x86emu_fpu_op_da_tab, mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 3: /* register to register */
+ stkelem = (u8)rl;
+ DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
+ break;
+ }
+#ifdef X86EMU_FPU_PRESENT
+ switch (mod) {
+ case 3:
+ x86emu_fpu_illegal();
+ break;
+ default:
+ switch (rh) {
+ case 0:
+ x86emu_fpu_M_iadd(X86EMU_FPU_SHORT, destoffset);
+ break;
+ case 1:
+ x86emu_fpu_M_imul(X86EMU_FPU_SHORT, destoffset);
+ break;
+ case 2:
+ x86emu_fpu_M_icom(X86EMU_FPU_SHORT, destoffset);
+ break;
+ case 3:
+ x86emu_fpu_M_icomp(X86EMU_FPU_SHORT, destoffset);
+ break;
+ case 4:
+ x86emu_fpu_M_isub(X86EMU_FPU_SHORT, destoffset);
+ break;
+ case 5:
+ x86emu_fpu_M_isubr(X86EMU_FPU_SHORT, destoffset);
+ break;
+ case 6:
+ x86emu_fpu_M_idiv(X86EMU_FPU_SHORT, destoffset);
+ break;
+ case 7:
+ x86emu_fpu_M_idivr(X86EMU_FPU_SHORT, destoffset);
+ break;
+ }
+ }
+#endif
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef DEBUG
+
+char *x86emu_fpu_op_db_tab[] = {
+ "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
+ "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
+
+ "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
+ "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
+
+ "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
+ "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
+};
+
+#endif /* DEBUG */
+
+/* opcode=0xdb */
+void x86emuOp_esc_coprocess_db(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (mod != 3) {
+ DECODE_PRINTINSTR32(x86emu_fpu_op_db_tab, mod, rh, rl);
+ } else if (rh == 4) { /* === 11 10 0 nnn */
+ switch (rl) {
+ case 0:
+ DECODE_PRINTF("FENI\n");
+ break;
+ case 1:
+ DECODE_PRINTF("FDISI\n");
+ break;
+ case 2:
+ DECODE_PRINTF("FCLEX\n");
+ break;
+ case 3:
+ DECODE_PRINTF("FINIT\n");
+ break;
+ }
+ } else {
+ DECODE_PRINTF2("ESC_DB %0x\n", (mod << 6) + (rh << 3) + (rl));
+ }
+#endif /* DEBUG */
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ break;
+ case 3: /* register to register */
+ break;
+ }
+#ifdef X86EMU_FPU_PRESENT
+ /* execute */
+ switch (mod) {
+ case 3:
+ switch (rh) {
+ case 4:
+ switch (rl) {
+ case 0:
+ x86emu_fpu_R_feni();
+ break;
+ case 1:
+ x86emu_fpu_R_fdisi();
+ break;
+ case 2:
+ x86emu_fpu_R_fclex();
+ break;
+ case 3:
+ x86emu_fpu_R_finit();
+ break;
+ default:
+ x86emu_fpu_illegal();
+ break;
+ }
+ break;
+ default:
+ x86emu_fpu_illegal();
+ break;
+ }
+ break;
+ default:
+ switch (rh) {
+ case 0:
+ x86emu_fpu_M_fild(X86EMU_FPU_SHORT, destoffset);
+ break;
+ case 1:
+ x86emu_fpu_illegal();
+ break;
+ case 2:
+ x86emu_fpu_M_fist(X86EMU_FPU_SHORT, destoffset);
+ break;
+ case 3:
+ x86emu_fpu_M_fistp(X86EMU_FPU_SHORT, destoffset);
+ break;
+ case 4:
+ x86emu_fpu_illegal();
+ break;
+ case 5:
+ x86emu_fpu_M_fld(X86EMU_FPU_LDBL, destoffset);
+ break;
+ case 6:
+ x86emu_fpu_illegal();
+ break;
+ case 7:
+ x86emu_fpu_M_fstp(X86EMU_FPU_LDBL, destoffset);
+ break;
+ }
+ }
+#endif
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef DEBUG
+char *x86emu_fpu_op_dc_tab[] = {
+ "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
+ "FCOMP\tQWORD PTR ",
+ "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
+ "FDIVR\tQWORD PTR ",
+
+ "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
+ "FCOMP\tQWORD PTR ",
+ "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
+ "FDIVR\tQWORD PTR ",
+
+ "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
+ "FCOMP\tQWORD PTR ",
+ "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
+ "FDIVR\tQWORD PTR ",
+
+ "FADD\t", "FMUL\t", "FCOM\t", "FCOMP\t",
+ "FSUBR\t", "FSUB\t", "FDIVR\t", "FDIV\t",
+};
+#endif /* DEBUG */
+
+/* opcode=0xdc */
+void x86emuOp_esc_coprocess_dc(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 stkelem;
+
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ DECODE_PRINTINSTR32(x86emu_fpu_op_dc_tab, mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 3: /* register to register */
+ stkelem = (u8)rl;
+ DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
+ break;
+ }
+#ifdef X86EMU_FPU_PRESENT
+ /* execute */
+ switch (mod) {
+ case 3:
+ switch (rh) {
+ case 0:
+ x86emu_fpu_R_fadd(stkelem, X86EMU_FPU_STKTOP);
+ break;
+ case 1:
+ x86emu_fpu_R_fmul(stkelem, X86EMU_FPU_STKTOP);
+ break;
+ case 2:
+ x86emu_fpu_R_fcom(stkelem, X86EMU_FPU_STKTOP);
+ break;
+ case 3:
+ x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP);
+ break;
+ case 4:
+ x86emu_fpu_R_fsubr(stkelem, X86EMU_FPU_STKTOP);
+ break;
+ case 5:
+ x86emu_fpu_R_fsub(stkelem, X86EMU_FPU_STKTOP);
+ break;
+ case 6:
+ x86emu_fpu_R_fdivr(stkelem, X86EMU_FPU_STKTOP);
+ break;
+ case 7:
+ x86emu_fpu_R_fdiv(stkelem, X86EMU_FPU_STKTOP);
+ break;
+ }
+ break;
+ default:
+ switch (rh) {
+ case 0:
+ x86emu_fpu_M_fadd(X86EMU_FPU_DOUBLE, destoffset);
+ break;
+ case 1:
+ x86emu_fpu_M_fmul(X86EMU_FPU_DOUBLE, destoffset);
+ break;
+ case 2:
+ x86emu_fpu_M_fcom(X86EMU_FPU_DOUBLE, destoffset);
+ break;
+ case 3:
+ x86emu_fpu_M_fcomp(X86EMU_FPU_DOUBLE, destoffset);
+ break;
+ case 4:
+ x86emu_fpu_M_fsub(X86EMU_FPU_DOUBLE, destoffset);
+ break;
+ case 5:
+ x86emu_fpu_M_fsubr(X86EMU_FPU_DOUBLE, destoffset);
+ break;
+ case 6:
+ x86emu_fpu_M_fdiv(X86EMU_FPU_DOUBLE, destoffset);
+ break;
+ case 7:
+ x86emu_fpu_M_fdivr(X86EMU_FPU_DOUBLE, destoffset);
+ break;
+ }
+ }
+#endif
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef DEBUG
+
+static char *x86emu_fpu_op_dd_tab[] = {
+ "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
+ "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
+
+ "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
+ "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
+
+ "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
+ "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
+
+ "FFREE\t", "FXCH\t", "FST\t", "FSTP\t",
+ "ESC_DD\t2C,", "ESC_DD\t2D,", "ESC_DD\t2E,", "ESC_DD\t2F,",
+};
+
+#endif /* DEBUG */
+
+/* opcode=0xdd */
+void x86emuOp_esc_coprocess_dd(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 stkelem;
+
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ DECODE_PRINTINSTR32(x86emu_fpu_op_dd_tab, mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 3: /* register to register */
+ stkelem = (u8)rl;
+ DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
+ break;
+ }
+#ifdef X86EMU_FPU_PRESENT
+ switch (mod) {
+ case 3:
+ switch (rh) {
+ case 0:
+ x86emu_fpu_R_ffree(stkelem);
+ break;
+ case 1:
+ x86emu_fpu_R_fxch(stkelem);
+ break;
+ case 2:
+ x86emu_fpu_R_fst(stkelem); /* register version */
+ break;
+ case 3:
+ x86emu_fpu_R_fstp(stkelem); /* register version */
+ break;
+ default:
+ x86emu_fpu_illegal();
+ break;
+ }
+ break;
+ default:
+ switch (rh) {
+ case 0:
+ x86emu_fpu_M_fld(X86EMU_FPU_DOUBLE, destoffset);
+ break;
+ case 1:
+ x86emu_fpu_illegal();
+ break;
+ case 2:
+ x86emu_fpu_M_fst(X86EMU_FPU_DOUBLE, destoffset);
+ break;
+ case 3:
+ x86emu_fpu_M_fstp(X86EMU_FPU_DOUBLE, destoffset);
+ break;
+ case 4:
+ x86emu_fpu_M_frstor(X86EMU_FPU_WORD, destoffset);
+ break;
+ case 5:
+ x86emu_fpu_illegal();
+ break;
+ case 6:
+ x86emu_fpu_M_fsave(X86EMU_FPU_WORD, destoffset);
+ break;
+ case 7:
+ x86emu_fpu_M_fstsw(X86EMU_FPU_WORD, destoffset);
+ break;
+ }
+ }
+#endif
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef DEBUG
+
+static char *x86emu_fpu_op_de_tab[] =
+{
+ "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
+ "FICOMP\tWORD PTR ",
+ "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
+ "FIDIVR\tWORD PTR ",
+
+ "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
+ "FICOMP\tWORD PTR ",
+ "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
+ "FIDIVR\tWORD PTR ",
+
+ "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
+ "FICOMP\tWORD PTR ",
+ "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
+ "FIDIVR\tWORD PTR ",
+
+ "FADDP\t", "FMULP\t", "FCOMP\t", "FCOMPP\t",
+ "FSUBRP\t", "FSUBP\t", "FDIVRP\t", "FDIVP\t",
+};
+
+#endif /* DEBUG */
+
+/* opcode=0xde */
+void x86emuOp_esc_coprocess_de(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 stkelem;
+
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ DECODE_PRINTINSTR32(x86emu_fpu_op_de_tab, mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 3: /* register to register */
+ stkelem = (u8)rl;
+ DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
+ break;
+ }
+#ifdef X86EMU_FPU_PRESENT
+ switch (mod) {
+ case 3:
+ switch (rh) {
+ case 0:
+ x86emu_fpu_R_faddp(stkelem, X86EMU_FPU_STKTOP);
+ break;
+ case 1:
+ x86emu_fpu_R_fmulp(stkelem, X86EMU_FPU_STKTOP);
+ break;
+ case 2:
+ x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP);
+ break;
+ case 3:
+ if (stkelem == 1)
+ x86emu_fpu_R_fcompp(stkelem, X86EMU_FPU_STKTOP);
+ else
+ x86emu_fpu_illegal();
+ break;
+ case 4:
+ x86emu_fpu_R_fsubrp(stkelem, X86EMU_FPU_STKTOP);
+ break;
+ case 5:
+ x86emu_fpu_R_fsubp(stkelem, X86EMU_FPU_STKTOP);
+ break;
+ case 6:
+ x86emu_fpu_R_fdivrp(stkelem, X86EMU_FPU_STKTOP);
+ break;
+ case 7:
+ x86emu_fpu_R_fdivp(stkelem, X86EMU_FPU_STKTOP);
+ break;
+ }
+ break;
+ default:
+ switch (rh) {
+ case 0:
+ x86emu_fpu_M_fiadd(X86EMU_FPU_WORD, destoffset);
+ break;
+ case 1:
+ x86emu_fpu_M_fimul(X86EMU_FPU_WORD, destoffset);
+ break;
+ case 2:
+ x86emu_fpu_M_ficom(X86EMU_FPU_WORD, destoffset);
+ break;
+ case 3:
+ x86emu_fpu_M_ficomp(X86EMU_FPU_WORD, destoffset);
+ break;
+ case 4:
+ x86emu_fpu_M_fisub(X86EMU_FPU_WORD, destoffset);
+ break;
+ case 5:
+ x86emu_fpu_M_fisubr(X86EMU_FPU_WORD, destoffset);
+ break;
+ case 6:
+ x86emu_fpu_M_fidiv(X86EMU_FPU_WORD, destoffset);
+ break;
+ case 7:
+ x86emu_fpu_M_fidivr(X86EMU_FPU_WORD, destoffset);
+ break;
+ }
+ }
+#endif
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR_NO_TRACE();
+}
+
+#ifdef DEBUG
+
+static char *x86emu_fpu_op_df_tab[] = {
+ /* mod == 00 */
+ "FILD\tWORD PTR ", "ESC_DF\t39\n", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
+ "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
+ "FISTP\tQWORD PTR ",
+
+ /* mod == 01 */
+ "FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
+ "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
+ "FISTP\tQWORD PTR ",
+
+ /* mod == 10 */
+ "FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
+ "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
+ "FISTP\tQWORD PTR ",
+
+ /* mod == 11 */
+ "FFREE\t", "FXCH\t", "FST\t", "FSTP\t",
+ "ESC_DF\t3C,", "ESC_DF\t3D,", "ESC_DF\t3E,", "ESC_DF\t3F,"
+};
+
+#endif /* DEBUG */
+
+/* opcode=0xdf */
+void x86emuOp_esc_coprocess_df(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 stkelem;
+
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ DECODE_PRINTINSTR32(x86emu_fpu_op_df_tab, mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ break;
+ case 3: /* register to register */
+ stkelem = (u8)rl;
+ DECODE_PRINTF2("\tST(%d)\n", stkelem);
+ break;
+ }
+#ifdef X86EMU_FPU_PRESENT
+ switch (mod) {
+ case 3:
+ switch (rh) {
+ case 0:
+ x86emu_fpu_R_ffree(stkelem);
+ break;
+ case 1:
+ x86emu_fpu_R_fxch(stkelem);
+ break;
+ case 2:
+ x86emu_fpu_R_fst(stkelem); /* register version */
+ break;
+ case 3:
+ x86emu_fpu_R_fstp(stkelem); /* register version */
+ break;
+ default:
+ x86emu_fpu_illegal();
+ break;
+ }
+ break;
+ default:
+ switch (rh) {
+ case 0:
+ x86emu_fpu_M_fild(X86EMU_FPU_WORD, destoffset);
+ break;
+ case 1:
+ x86emu_fpu_illegal();
+ break;
+ case 2:
+ x86emu_fpu_M_fist(X86EMU_FPU_WORD, destoffset);
+ break;
+ case 3:
+ x86emu_fpu_M_fistp(X86EMU_FPU_WORD, destoffset);
+ break;
+ case 4:
+ x86emu_fpu_M_fbld(X86EMU_FPU_BSD, destoffset);
+ break;
+ case 5:
+ x86emu_fpu_M_fild(X86EMU_FPU_LONG, destoffset);
+ break;
+ case 6:
+ x86emu_fpu_M_fbstp(X86EMU_FPU_BSD, destoffset);
+ break;
+ case 7:
+ x86emu_fpu_M_fistp(X86EMU_FPU_LONG, destoffset);
+ break;
+ }
+ }
+#endif
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR_NO_TRACE();
+}
diff --git a/cfe/cfe/x86emu/ops.c b/cfe/cfe/x86emu/ops.c
new file mode 100644
index 0000000..46a20b2
--- /dev/null
+++ b/cfe/cfe/x86emu/ops.c
@@ -0,0 +1,11686 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: This file includes subroutines to implement the decoding
+* and emulation of all the x86 processor instructions.
+*
+* There are approximately 250 subroutines in here, which correspond
+* to the 256 byte-"opcodes" found on the 8086. The table which
+* dispatches this is found in the files optab.[ch].
+*
+* Each opcode proc has a comment preceeding it which gives it's table
+* address. Several opcodes are missing (undefined) in the table.
+*
+* Each proc includes information for decoding (DECODE_PRINTF and
+* DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc
+* functions (START_OF_INSTR, END_OF_INSTR).
+*
+* Many of the procedures are *VERY* similar in coding. This has
+* allowed for a very large amount of code to be generated in a fairly
+* short amount of time (i.e. cut, paste, and modify). The result is
+* that much of the code below could have been folded into subroutines
+* for a large reduction in size of this file. The downside would be
+* that there would be a penalty in execution speed. The file could
+* also have been *MUCH* larger by inlining certain functions which
+* were called. This could have resulted even faster execution. The
+* prime directive I used to decide whether to inline the code or to
+* modularize it, was basically: 1) no unnecessary subroutine calls,
+* 2) no routines more than about 200 lines in size, and 3) modularize
+* any code that I might not get right the first time. The fetch_*
+* subroutines fall into the latter category. The The decode_* fall
+* into the second category. The coding of the "switch(mod){ .... }"
+* in many of the subroutines below falls into the first category.
+* Especially, the coding of {add,and,or,sub,...}_{byte,word}
+* subroutines are an especially glaring case of the third guideline.
+* Since so much of the code is cloned from other modules (compare
+* opcode #00 to opcode #01), making the basic operations subroutine
+* calls is especially important; otherwise mistakes in coding an
+* "add" would represent a nightmare in maintenance.
+*
+****************************************************************************/
+
+/* $XFree86: xc/extras/x86emu/src/x86emu/ops.c,v 1.4 2000/04/17 16:29:45 eich Exp $ */
+
+#include "x86emu/x86emui.h"
+#include "x86emu/ops_protos.h"
+#include "lib_printf.h"
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+PARAMETERS:
+op1 - Instruction op code
+
+REMARKS:
+Handles illegal opcodes.
+****************************************************************************/
+void x86emuOp_illegal_op(
+ u8 op1)
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
+ TRACE_REGS();
+ printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
+ M.x86.R_CS, M.x86.R_IP-1,op1);
+ HALT_SYS();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x00
+****************************************************************************/
+void x86emuOp_add_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 *destreg, *srcreg;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADD\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x01
+****************************************************************************/
+void x86emuOp_add_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADD\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = add_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x02
+****************************************************************************/
+void x86emuOp_add_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADD\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_byte(*destreg, srcval);
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_byte(*destreg, srcval);
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_byte(*destreg, srcval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x03
+****************************************************************************/
+void x86emuOp_add_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADD\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_word(*destreg, srcval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_word(*destreg, srcval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = add_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x04
+****************************************************************************/
+void x86emuOp_add_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADD\tAL,");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ M.x86.R_AL = add_byte(M.x86.R_AL, srcval);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x05
+****************************************************************************/
+void x86emuOp_add_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("ADD\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("ADD\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = add_long(M.x86.R_EAX, srcval);
+ } else {
+ M.x86.R_AX = add_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x06
+****************************************************************************/
+void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("PUSH\tES\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_ES);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x07
+****************************************************************************/
+void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("POP\tES\n");
+ TRACE_AND_STEP();
+ M.x86.R_ES = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x08
+****************************************************************************/
+void x86emuOp_or_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("OR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x09
+****************************************************************************/
+void x86emuOp_or_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("OR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = or_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0a
+****************************************************************************/
+void x86emuOp_or_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("OR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_byte(*destreg, srcval);
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_byte(*destreg, srcval);
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_byte(*destreg, srcval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0b
+****************************************************************************/
+void x86emuOp_or_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("OR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_word(*destreg, srcval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_word(*destreg, srcval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = or_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0c
+****************************************************************************/
+void x86emuOp_or_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("OR\tAL,");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ M.x86.R_AL = or_byte(M.x86.R_AL, srcval);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0d
+****************************************************************************/
+void x86emuOp_or_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("OR\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("OR\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = or_long(M.x86.R_EAX, srcval);
+ } else {
+ M.x86.R_AX = or_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0e
+****************************************************************************/
+void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("PUSH\tCS\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_CS);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f. Escape for two-byte opcode (286 or better)
+****************************************************************************/
+void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1))
+{
+ u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
+ INC_DECODED_INST_LEN(1);
+ (*x86emu_optab2[op2])(op2);
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x10
+****************************************************************************/
+void x86emuOp_adc_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADC\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x11
+****************************************************************************/
+void x86emuOp_adc_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADC\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = adc_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x12
+****************************************************************************/
+void x86emuOp_adc_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADC\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_byte(*destreg, srcval);
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_byte(*destreg, srcval);
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_byte(*destreg, srcval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x13
+****************************************************************************/
+void x86emuOp_adc_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADC\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_word(*destreg, srcval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_word(*destreg, srcval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = adc_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x14
+****************************************************************************/
+void x86emuOp_adc_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("ADC\tAL,");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ M.x86.R_AL = adc_byte(M.x86.R_AL, srcval);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x15
+****************************************************************************/
+void x86emuOp_adc_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("ADC\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("ADC\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = adc_long(M.x86.R_EAX, srcval);
+ } else {
+ M.x86.R_AX = adc_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x16
+****************************************************************************/
+void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("PUSH\tSS\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_SS);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x17
+****************************************************************************/
+void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("POP\tSS\n");
+ TRACE_AND_STEP();
+ M.x86.R_SS = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x18
+****************************************************************************/
+void x86emuOp_sbb_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SBB\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x19
+****************************************************************************/
+void x86emuOp_sbb_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SBB\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sbb_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1a
+****************************************************************************/
+void x86emuOp_sbb_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SBB\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_byte(*destreg, srcval);
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_byte(*destreg, srcval);
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_byte(*destreg, srcval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1b
+****************************************************************************/
+void x86emuOp_sbb_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SBB\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_word(*destreg, srcval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_word(*destreg, srcval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sbb_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1c
+****************************************************************************/
+void x86emuOp_sbb_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SBB\tAL,");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ M.x86.R_AL = sbb_byte(M.x86.R_AL, srcval);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1d
+****************************************************************************/
+void x86emuOp_sbb_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("SBB\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("SBB\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = sbb_long(M.x86.R_EAX, srcval);
+ } else {
+ M.x86.R_AX = sbb_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1e
+****************************************************************************/
+void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("PUSH\tDS\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_DS);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x1f
+****************************************************************************/
+void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("POP\tDS\n");
+ TRACE_AND_STEP();
+ M.x86.R_DS = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x20
+****************************************************************************/
+void x86emuOp_and_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("AND\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x21
+****************************************************************************/
+void x86emuOp_and_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("AND\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = and_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x22
+****************************************************************************/
+void x86emuOp_and_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("AND\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_byte(*destreg, srcval);
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_byte(*destreg, srcval);
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_byte(*destreg, srcval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x23
+****************************************************************************/
+void x86emuOp_and_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("AND\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_long(*destreg, srcval);
+ break;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_word(*destreg, srcval);
+ break;
+ }
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_word(*destreg, srcval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = and_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x24
+****************************************************************************/
+void x86emuOp_and_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("AND\tAL,");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ M.x86.R_AL = and_byte(M.x86.R_AL, srcval);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x25
+****************************************************************************/
+void x86emuOp_and_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("AND\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("AND\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = and_long(M.x86.R_EAX, srcval);
+ } else {
+ M.x86.R_AX = and_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x26
+****************************************************************************/
+void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("ES:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_ES;
+ /*
+ * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
+ * opcode subroutines we do not want to do this.
+ */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x27
+****************************************************************************/
+void x86emuOp_daa(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("DAA\n");
+ TRACE_AND_STEP();
+ M.x86.R_AL = daa_byte(M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x28
+****************************************************************************/
+void x86emuOp_sub_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SUB\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x29
+****************************************************************************/
+void x86emuOp_sub_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SUB\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = sub_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2a
+****************************************************************************/
+void x86emuOp_sub_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SUB\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_byte(*destreg, srcval);
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_byte(*destreg, srcval);
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_byte(*destreg, srcval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2b
+****************************************************************************/
+void x86emuOp_sub_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SUB\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_word(*destreg, srcval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_word(*destreg, srcval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = sub_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2c
+****************************************************************************/
+void x86emuOp_sub_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SUB\tAL,");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ M.x86.R_AL = sub_byte(M.x86.R_AL, srcval);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2d
+****************************************************************************/
+void x86emuOp_sub_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("SUB\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("SUB\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = sub_long(M.x86.R_EAX, srcval);
+ } else {
+ M.x86.R_AX = sub_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2e
+****************************************************************************/
+void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("CS:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_CS;
+ /* note no DECODE_CLEAR_SEGOVR here. */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x2f
+****************************************************************************/
+void x86emuOp_das(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("DAS\n");
+ TRACE_AND_STEP();
+ M.x86.R_AL = das_byte(M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x30
+****************************************************************************/
+void x86emuOp_xor_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XOR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_byte(destval, *srcreg);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x31
+****************************************************************************/
+void x86emuOp_xor_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XOR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_long(destval, *srcreg);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = xor_word(destval, *srcreg);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x32
+****************************************************************************/
+void x86emuOp_xor_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XOR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_byte(*destreg, srcval);
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_byte(*destreg, srcval);
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_byte(*destreg, srcval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x33
+****************************************************************************/
+void x86emuOp_xor_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XOR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_word(*destreg, srcval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_word(*destreg, srcval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = xor_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x34
+****************************************************************************/
+void x86emuOp_xor_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XOR\tAL,");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ M.x86.R_AL = xor_byte(M.x86.R_AL, srcval);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x35
+****************************************************************************/
+void x86emuOp_xor_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("XOR\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("XOR\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = xor_long(M.x86.R_EAX, srcval);
+ } else {
+ M.x86.R_AX = xor_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x36
+****************************************************************************/
+void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("SS:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_SS;
+ /* no DECODE_CLEAR_SEGOVR ! */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x37
+****************************************************************************/
+void x86emuOp_aaa(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("AAA\n");
+ TRACE_AND_STEP();
+ M.x86.R_AX = aaa_word(M.x86.R_AX);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x38
+****************************************************************************/
+void x86emuOp_cmp_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 *destreg, *srcreg;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CMP\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_byte(destval, *srcreg);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_byte(destval, *srcreg);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_byte(destval, *srcreg);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x39
+****************************************************************************/
+void x86emuOp_cmp_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CMP\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_long(destval, *srcreg);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_word(destval, *srcreg);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_long(destval, *srcreg);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_word(destval, *srcreg);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_long(destval, *srcreg);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_word(destval, *srcreg);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3a
+****************************************************************************/
+void x86emuOp_cmp_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CMP\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_byte(*destreg, srcval);
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_byte(*destreg, srcval);
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_byte(*destreg, srcval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3b
+****************************************************************************/
+void x86emuOp_cmp_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CMP\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_word(*destreg, srcval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_word(*destreg, srcval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ cmp_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3c
+****************************************************************************/
+void x86emuOp_cmp_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CMP\tAL,");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ cmp_byte(M.x86.R_AL, srcval);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3d
+****************************************************************************/
+void x86emuOp_cmp_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("CMP\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("CMP\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ cmp_long(M.x86.R_EAX, srcval);
+ } else {
+ cmp_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3e
+****************************************************************************/
+void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("DS:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_DS;
+ /* NO DECODE_CLEAR_SEGOVR! */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x3f
+****************************************************************************/
+void x86emuOp_aas(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("AAS\n");
+ TRACE_AND_STEP();
+ M.x86.R_AX = aas_word(M.x86.R_AX);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x40
+****************************************************************************/
+void x86emuOp_inc_AX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tEAX\n");
+ } else {
+ DECODE_PRINTF("INC\tAX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = inc_long(M.x86.R_EAX);
+ } else {
+ M.x86.R_AX = inc_word(M.x86.R_AX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x41
+****************************************************************************/
+void x86emuOp_inc_CX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tECX\n");
+ } else {
+ DECODE_PRINTF("INC\tCX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ECX = inc_long(M.x86.R_ECX);
+ } else {
+ M.x86.R_CX = inc_word(M.x86.R_CX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x42
+****************************************************************************/
+void x86emuOp_inc_DX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tEDX\n");
+ } else {
+ DECODE_PRINTF("INC\tDX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDX = inc_long(M.x86.R_EDX);
+ } else {
+ M.x86.R_DX = inc_word(M.x86.R_DX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x43
+****************************************************************************/
+void x86emuOp_inc_BX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tEBX\n");
+ } else {
+ DECODE_PRINTF("INC\tBX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EBX = inc_long(M.x86.R_EBX);
+ } else {
+ M.x86.R_BX = inc_word(M.x86.R_BX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x44
+****************************************************************************/
+void x86emuOp_inc_SP(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tESP\n");
+ } else {
+ DECODE_PRINTF("INC\tSP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ESP = inc_long(M.x86.R_ESP);
+ } else {
+ M.x86.R_SP = inc_word(M.x86.R_SP);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x45
+****************************************************************************/
+void x86emuOp_inc_BP(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tEBP\n");
+ } else {
+ DECODE_PRINTF("INC\tBP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EBP = inc_long(M.x86.R_EBP);
+ } else {
+ M.x86.R_BP = inc_word(M.x86.R_BP);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x46
+****************************************************************************/
+void x86emuOp_inc_SI(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tESI\n");
+ } else {
+ DECODE_PRINTF("INC\tSI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ESI = inc_long(M.x86.R_ESI);
+ } else {
+ M.x86.R_SI = inc_word(M.x86.R_SI);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x47
+****************************************************************************/
+void x86emuOp_inc_DI(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tEDI\n");
+ } else {
+ DECODE_PRINTF("INC\tDI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDI = inc_long(M.x86.R_EDI);
+ } else {
+ M.x86.R_DI = inc_word(M.x86.R_DI);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x48
+****************************************************************************/
+void x86emuOp_dec_AX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tEAX\n");
+ } else {
+ DECODE_PRINTF("DEC\tAX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = dec_long(M.x86.R_EAX);
+ } else {
+ M.x86.R_AX = dec_word(M.x86.R_AX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x49
+****************************************************************************/
+void x86emuOp_dec_CX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tECX\n");
+ } else {
+ DECODE_PRINTF("DEC\tCX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ECX = dec_long(M.x86.R_ECX);
+ } else {
+ M.x86.R_CX = dec_word(M.x86.R_CX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4a
+****************************************************************************/
+void x86emuOp_dec_DX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tEDX\n");
+ } else {
+ DECODE_PRINTF("DEC\tDX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDX = dec_long(M.x86.R_EDX);
+ } else {
+ M.x86.R_DX = dec_word(M.x86.R_DX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4b
+****************************************************************************/
+void x86emuOp_dec_BX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tEBX\n");
+ } else {
+ DECODE_PRINTF("DEC\tBX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EBX = dec_long(M.x86.R_EBX);
+ } else {
+ M.x86.R_BX = dec_word(M.x86.R_BX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4c
+****************************************************************************/
+void x86emuOp_dec_SP(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tESP\n");
+ } else {
+ DECODE_PRINTF("DEC\tSP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ESP = dec_long(M.x86.R_ESP);
+ } else {
+ M.x86.R_SP = dec_word(M.x86.R_SP);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4d
+****************************************************************************/
+void x86emuOp_dec_BP(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tEBP\n");
+ } else {
+ DECODE_PRINTF("DEC\tBP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EBP = dec_long(M.x86.R_EBP);
+ } else {
+ M.x86.R_BP = dec_word(M.x86.R_BP);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4e
+****************************************************************************/
+void x86emuOp_dec_SI(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tESI\n");
+ } else {
+ DECODE_PRINTF("DEC\tSI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ESI = dec_long(M.x86.R_ESI);
+ } else {
+ M.x86.R_SI = dec_word(M.x86.R_SI);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x4f
+****************************************************************************/
+void x86emuOp_dec_DI(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tEDI\n");
+ } else {
+ DECODE_PRINTF("DEC\tDI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDI = dec_long(M.x86.R_EDI);
+ } else {
+ M.x86.R_DI = dec_word(M.x86.R_DI);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x50
+****************************************************************************/
+void x86emuOp_push_AX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSH\tEAX\n");
+ } else {
+ DECODE_PRINTF("PUSH\tAX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_EAX);
+ } else {
+ push_word(M.x86.R_AX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x51
+****************************************************************************/
+void x86emuOp_push_CX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSH\tECX\n");
+ } else {
+ DECODE_PRINTF("PUSH\tCX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_ECX);
+ } else {
+ push_word(M.x86.R_CX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x52
+****************************************************************************/
+void x86emuOp_push_DX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSH\tEDX\n");
+ } else {
+ DECODE_PRINTF("PUSH\tDX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_EDX);
+ } else {
+ push_word(M.x86.R_DX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x53
+****************************************************************************/
+void x86emuOp_push_BX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSH\tEBX\n");
+ } else {
+ DECODE_PRINTF("PUSH\tBX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_EBX);
+ } else {
+ push_word(M.x86.R_BX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x54
+****************************************************************************/
+void x86emuOp_push_SP(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSH\tESP\n");
+ } else {
+ DECODE_PRINTF("PUSH\tSP\n");
+ }
+ TRACE_AND_STEP();
+ /* Always push (E)SP, since we are emulating an i386 and above
+ * processor. This is necessary as some BIOS'es use this to check
+ * what type of processor is in the system.
+ */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_ESP);
+ } else {
+ push_word((u16)(M.x86.R_SP));
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x55
+****************************************************************************/
+void x86emuOp_push_BP(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSH\tEBP\n");
+ } else {
+ DECODE_PRINTF("PUSH\tBP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_EBP);
+ } else {
+ push_word(M.x86.R_BP);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x56
+****************************************************************************/
+void x86emuOp_push_SI(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSH\tESI\n");
+ } else {
+ DECODE_PRINTF("PUSH\tSI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_ESI);
+ } else {
+ push_word(M.x86.R_SI);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x57
+****************************************************************************/
+void x86emuOp_push_DI(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSH\tEDI\n");
+ } else {
+ DECODE_PRINTF("PUSH\tDI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_EDI);
+ } else {
+ push_word(M.x86.R_DI);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x58
+****************************************************************************/
+void x86emuOp_pop_AX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POP\tEAX\n");
+ } else {
+ DECODE_PRINTF("POP\tAX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = pop_long();
+ } else {
+ M.x86.R_AX = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x59
+****************************************************************************/
+void x86emuOp_pop_CX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POP\tECX\n");
+ } else {
+ DECODE_PRINTF("POP\tCX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ECX = pop_long();
+ } else {
+ M.x86.R_CX = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5a
+****************************************************************************/
+void x86emuOp_pop_DX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POP\tEDX\n");
+ } else {
+ DECODE_PRINTF("POP\tDX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDX = pop_long();
+ } else {
+ M.x86.R_DX = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5b
+****************************************************************************/
+void x86emuOp_pop_BX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POP\tEBX\n");
+ } else {
+ DECODE_PRINTF("POP\tBX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EBX = pop_long();
+ } else {
+ M.x86.R_BX = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5c
+****************************************************************************/
+void x86emuOp_pop_SP(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POP\tESP\n");
+ } else {
+ DECODE_PRINTF("POP\tSP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ESP = pop_long();
+ } else {
+ M.x86.R_SP = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5d
+****************************************************************************/
+void x86emuOp_pop_BP(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POP\tEBP\n");
+ } else {
+ DECODE_PRINTF("POP\tBP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EBP = pop_long();
+ } else {
+ M.x86.R_BP = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5e
+****************************************************************************/
+void x86emuOp_pop_SI(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POP\tESI\n");
+ } else {
+ DECODE_PRINTF("POP\tSI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ESI = pop_long();
+ } else {
+ M.x86.R_SI = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x5f
+****************************************************************************/
+void x86emuOp_pop_DI(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POP\tEDI\n");
+ } else {
+ DECODE_PRINTF("POP\tDI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDI = pop_long();
+ } else {
+ M.x86.R_DI = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x60
+****************************************************************************/
+void x86emuOp_push_all(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSHAD\n");
+ } else {
+ DECODE_PRINTF("PUSHA\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 old_sp = M.x86.R_ESP;
+
+ push_long(M.x86.R_EAX);
+ push_long(M.x86.R_ECX);
+ push_long(M.x86.R_EDX);
+ push_long(M.x86.R_EBX);
+ push_long(old_sp);
+ push_long(M.x86.R_EBP);
+ push_long(M.x86.R_ESI);
+ push_long(M.x86.R_EDI);
+ } else {
+ u16 old_sp = M.x86.R_SP;
+
+ push_word(M.x86.R_AX);
+ push_word(M.x86.R_CX);
+ push_word(M.x86.R_DX);
+ push_word(M.x86.R_BX);
+ push_word(old_sp);
+ push_word(M.x86.R_BP);
+ push_word(M.x86.R_SI);
+ push_word(M.x86.R_DI);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x61
+****************************************************************************/
+void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POPAD\n");
+ } else {
+ DECODE_PRINTF("POPA\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDI = pop_long();
+ M.x86.R_ESI = pop_long();
+ M.x86.R_EBP = pop_long();
+ M.x86.R_ESP += 4; /* skip ESP */
+ M.x86.R_EBX = pop_long();
+ M.x86.R_EDX = pop_long();
+ M.x86.R_ECX = pop_long();
+ M.x86.R_EAX = pop_long();
+ } else {
+ M.x86.R_DI = pop_word();
+ M.x86.R_SI = pop_word();
+ M.x86.R_BP = pop_word();
+ M.x86.R_SP += 2; /* skip SP */
+ M.x86.R_BX = pop_word();
+ M.x86.R_DX = pop_word();
+ M.x86.R_CX = pop_word();
+ M.x86.R_AX = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
+/*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x64
+****************************************************************************/
+void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("FS:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_FS;
+ /*
+ * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
+ * opcode subroutines we do not want to do this.
+ */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x65
+****************************************************************************/
+void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("GS:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_SEGOVR_GS;
+ /*
+ * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
+ * opcode subroutines we do not want to do this.
+ */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x66 - prefix for 32-bit register
+****************************************************************************/
+void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("DATA:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_PREFIX_DATA;
+ /* note no DECODE_CLEAR_SEGOVR here. */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x67 - prefix for 32-bit address
+****************************************************************************/
+void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("ADDR:\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_PREFIX_ADDR;
+ /* note no DECODE_CLEAR_SEGOVR here. */
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x68
+****************************************************************************/
+void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 imm;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ imm = fetch_long_imm();
+ } else {
+ imm = fetch_word_imm();
+ }
+ DECODE_PRINTF2("PUSH\t%x\n", imm);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(imm);
+ } else {
+ push_word((u16)imm);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x69
+****************************************************************************/
+void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("IMUL\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+ s32 imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+ s16 imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ res = (s16)srcval * (s16)imm;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+ s32 imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+ s16 imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ res = (s16)srcval * (s16)imm;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+ s32 imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+ s16 imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ res = (s16)srcval * (s16)imm;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+ u32 res_lo,res_hi;
+ s32 imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg,*srcreg;
+ u32 res;
+ s16 imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ res = (s16)*srcreg * (s16)imm;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6a
+****************************************************************************/
+void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
+{
+ s16 imm;
+
+ START_OF_INSTR();
+ imm = (s8)fetch_byte_imm();
+ DECODE_PRINTF2("PUSH\t%d\n", imm);
+ TRACE_AND_STEP();
+ push_word(imm);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6b
+****************************************************************************/
+void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ s8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("IMUL\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ res = (s16)srcval * (s16)imm;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ res = (s16)srcval * (s16)imm;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ res = (s16)srcval * (s16)imm;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+ u32 res_lo,res_hi;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg,*srcreg;
+ u32 res;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%d\n", (s32)imm);
+ res = (s16)*srcreg * (s16)imm;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6c
+****************************************************************************/
+void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("INSB\n");
+ ins(1);
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6d
+****************************************************************************/
+void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INSD\n");
+ ins(4);
+ } else {
+ DECODE_PRINTF("INSW\n");
+ ins(2);
+ }
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6e
+****************************************************************************/
+void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("OUTSB\n");
+ outs(1);
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x6f
+****************************************************************************/
+void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("OUTSD\n");
+ outs(4);
+ } else {
+ DECODE_PRINTF("OUTSW\n");
+ outs(2);
+ }
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x70
+****************************************************************************/
+void x86emuOp_jump_near_O(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if overflow flag is set */
+ START_OF_INSTR();
+ DECODE_PRINTF("JO\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_OF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x71
+****************************************************************************/
+void x86emuOp_jump_near_NO(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if overflow is not set */
+ START_OF_INSTR();
+ DECODE_PRINTF("JNO\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (!ACCESS_FLAG(F_OF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x72
+****************************************************************************/
+void x86emuOp_jump_near_B(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if carry flag is set. */
+ START_OF_INSTR();
+ DECODE_PRINTF("JB\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_CF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x73
+****************************************************************************/
+void x86emuOp_jump_near_NB(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if carry flag is clear. */
+ START_OF_INSTR();
+ DECODE_PRINTF("JNB\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (!ACCESS_FLAG(F_CF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x74
+****************************************************************************/
+void x86emuOp_jump_near_Z(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if zero flag is set. */
+ START_OF_INSTR();
+ DECODE_PRINTF("JZ\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_ZF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x75
+****************************************************************************/
+void x86emuOp_jump_near_NZ(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if zero flag is clear. */
+ START_OF_INSTR();
+ DECODE_PRINTF("JNZ\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (!ACCESS_FLAG(F_ZF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x76
+****************************************************************************/
+void x86emuOp_jump_near_BE(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if carry flag is set or if the zero
+ flag is set. */
+ START_OF_INSTR();
+ DECODE_PRINTF("JBE\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x77
+****************************************************************************/
+void x86emuOp_jump_near_NBE(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if carry flag is clear and if the zero
+ flag is clear */
+ START_OF_INSTR();
+ DECODE_PRINTF("JNBE\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (!(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x78
+****************************************************************************/
+void x86emuOp_jump_near_S(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if sign flag is set */
+ START_OF_INSTR();
+ DECODE_PRINTF("JS\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_SF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x79
+****************************************************************************/
+void x86emuOp_jump_near_NS(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if sign flag is clear */
+ START_OF_INSTR();
+ DECODE_PRINTF("JNS\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (!ACCESS_FLAG(F_SF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7a
+****************************************************************************/
+void x86emuOp_jump_near_P(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if parity flag is set (even parity) */
+ START_OF_INSTR();
+ DECODE_PRINTF("JP\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_PF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7b
+****************************************************************************/
+void x86emuOp_jump_near_NP(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+
+ /* jump to byte offset if parity flag is clear (odd parity) */
+ START_OF_INSTR();
+ DECODE_PRINTF("JNP\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (!ACCESS_FLAG(F_PF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7c
+****************************************************************************/
+void x86emuOp_jump_near_L(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+ int sf, of;
+
+ /* jump to byte offset if sign flag not equal to overflow flag. */
+ START_OF_INSTR();
+ DECODE_PRINTF("JL\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ sf = ACCESS_FLAG(F_SF) != 0;
+ of = ACCESS_FLAG(F_OF) != 0;
+ if (sf ^ of)
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7d
+****************************************************************************/
+void x86emuOp_jump_near_NL(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+ int sf, of;
+
+ /* jump to byte offset if sign flag not equal to overflow flag. */
+ START_OF_INSTR();
+ DECODE_PRINTF("JNL\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ sf = ACCESS_FLAG(F_SF) != 0;
+ of = ACCESS_FLAG(F_OF) != 0;
+ /* note: inverse of above, but using == instead of xor. */
+ if (sf == of)
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7e
+****************************************************************************/
+void x86emuOp_jump_near_LE(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+ int sf, of;
+
+ /* jump to byte offset if sign flag not equal to overflow flag
+ or the zero flag is set */
+ START_OF_INSTR();
+ DECODE_PRINTF("JLE\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ sf = ACCESS_FLAG(F_SF) != 0;
+ of = ACCESS_FLAG(F_OF) != 0;
+ if ((sf ^ of) || ACCESS_FLAG(F_ZF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x7f
+****************************************************************************/
+void x86emuOp_jump_near_NLE(u8 X86EMU_UNUSED(op1))
+{
+ s8 offset;
+ u16 target;
+ int sf, of;
+
+ /* jump to byte offset if sign flag equal to overflow flag.
+ and the zero flag is clear */
+ START_OF_INSTR();
+ DECODE_PRINTF("JNLE\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + (s16)offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ sf = ACCESS_FLAG(F_SF) != 0;
+ of = ACCESS_FLAG(F_OF) != 0;
+ if ((sf == of) && !ACCESS_FLAG(F_ZF))
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+static u8 (*opc80_byte_operation[])(u8 d, u8 s) =
+{
+ add_byte, /* 00 */
+ or_byte, /* 01 */
+ adc_byte, /* 02 */
+ sbb_byte, /* 03 */
+ and_byte, /* 04 */
+ sub_byte, /* 05 */
+ xor_byte, /* 06 */
+ cmp_byte, /* 07 */
+};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x80
+****************************************************************************/
+void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 imm;
+ u8 destval;
+
+ /*
+ * Weirdo special case instruction format. Part of the opcode
+ * held below in "RH". Doubly nested case would result, except
+ * that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ADD\t");
+ break;
+ case 1:
+ DECODE_PRINTF("OR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("ADC\t");
+ break;
+ case 3:
+ DECODE_PRINTF("SBB\t");
+ break;
+ case 4:
+ DECODE_PRINTF("AND\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SUB\t");
+ break;
+ case 6:
+ DECODE_PRINTF("XOR\t");
+ break;
+ case 7:
+ DECODE_PRINTF("CMP\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ switch (mod) {
+ case 0:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc80_byte_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc80_byte_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc80_byte_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc80_byte_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+static u16 (*opc81_word_operation[])(u16 d, u16 s) =
+{
+ add_word, /*00 */
+ or_word, /*01 */
+ adc_word, /*02 */
+ sbb_word, /*03 */
+ and_word, /*04 */
+ sub_word, /*05 */
+ xor_word, /*06 */
+ cmp_word, /*07 */
+};
+
+static u32 (*opc81_long_operation[])(u32 d, u32 s) =
+{
+ add_long, /*00 */
+ or_long, /*01 */
+ adc_long, /*02 */
+ sbb_long, /*03 */
+ and_long, /*04 */
+ sub_long, /*05 */
+ xor_long, /*06 */
+ cmp_long, /*07 */
+};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x81
+****************************************************************************/
+void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ /*
+ * Weirdo special case instruction format. Part of the opcode
+ * held below in "RH". Doubly nested case would result, except
+ * that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ADD\t");
+ break;
+ case 1:
+ DECODE_PRINTF("OR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("ADC\t");
+ break;
+ case 3:
+ DECODE_PRINTF("SBB\t");
+ break;
+ case 4:
+ DECODE_PRINTF("AND\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SUB\t");
+ break;
+ case 6:
+ DECODE_PRINTF("XOR\t");
+ break;
+ case 7:
+ DECODE_PRINTF("CMP\t");
+ break;
+ }
+ }
+#endif
+ /*
+ * Know operation, decode the mod byte to find the addressing
+ * mode.
+ */
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc81_long_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval,imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc81_word_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc81_long_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval,imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc81_word_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc81_long_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval,imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc81_word_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 destval,imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ imm = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc81_long_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ } else {
+ u16 *destreg;
+ u16 destval,imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ imm = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc81_word_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+static u8 (*opc82_byte_operation[])(u8 s, u8 d) =
+{
+ add_byte, /*00 */
+ or_byte, /*01 *//*YYY UNUSED ???? */
+ adc_byte, /*02 */
+ sbb_byte, /*03 */
+ and_byte, /*04 *//*YYY UNUSED ???? */
+ sub_byte, /*05 */
+ xor_byte, /*06 *//*YYY UNUSED ???? */
+ cmp_byte, /*07 */
+};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x82
+****************************************************************************/
+void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 imm;
+ u8 destval;
+
+ /*
+ * Weirdo special case instruction format. Part of the opcode
+ * held below in "RH". Doubly nested case would result, except
+ * that the decoded instruction Similar to opcode 81, except that
+ * the immediate byte is sign extended to a word length.
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ADD\t");
+ break;
+ case 1:
+ DECODE_PRINTF("OR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("ADC\t");
+ break;
+ case 3:
+ DECODE_PRINTF("SBB\t");
+ break;
+ case 4:
+ DECODE_PRINTF("AND\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SUB\t");
+ break;
+ case 6:
+ DECODE_PRINTF("XOR\t");
+ break;
+ case 7:
+ DECODE_PRINTF("CMP\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ switch (mod) {
+ case 0:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ destval = fetch_data_byte(destoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc82_byte_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ destval = fetch_data_byte(destoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc82_byte_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ destval = fetch_data_byte(destoffset);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc82_byte_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc82_byte_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+static u16 (*opc83_word_operation[])(u16 s, u16 d) =
+{
+ add_word, /*00 */
+ or_word, /*01 *//*YYY UNUSED ???? */
+ adc_word, /*02 */
+ sbb_word, /*03 */
+ and_word, /*04 *//*YYY UNUSED ???? */
+ sub_word, /*05 */
+ xor_word, /*06 *//*YYY UNUSED ???? */
+ cmp_word, /*07 */
+};
+
+static u32 (*opc83_long_operation[])(u32 s, u32 d) =
+{
+ add_long, /*00 */
+ or_long, /*01 *//*YYY UNUSED ???? */
+ adc_long, /*02 */
+ sbb_long, /*03 */
+ and_long, /*04 *//*YYY UNUSED ???? */
+ sub_long, /*05 */
+ xor_long, /*06 *//*YYY UNUSED ???? */
+ cmp_long, /*07 */
+};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x83
+****************************************************************************/
+void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ /*
+ * Weirdo special case instruction format. Part of the opcode
+ * held below in "RH". Doubly nested case would result, except
+ * that the decoded instruction Similar to opcode 81, except that
+ * the immediate byte is sign extended to a word length.
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ADD\t");
+ break;
+ case 1:
+ DECODE_PRINTF("OR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("ADC\t");
+ break;
+ case 3:
+ DECODE_PRINTF("SBB\t");
+ break;
+ case 4:
+ DECODE_PRINTF("AND\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SUB\t");
+ break;
+ case 6:
+ DECODE_PRINTF("XOR\t");
+ break;
+ case 7:
+ DECODE_PRINTF("CMP\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ destval = fetch_data_long(destoffset);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc83_long_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval,imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ destval = fetch_data_word(destoffset);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc83_word_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ destval = fetch_data_long(destoffset);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc83_long_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval,imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ destval = fetch_data_word(destoffset);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc83_word_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ destval = fetch_data_long(destoffset);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc83_long_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval,imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ destval = fetch_data_word(destoffset);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc83_word_operation[rh]) (destval, imm);
+ if (rh != 7)
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 destval,imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc83_long_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ } else {
+ u16 *destreg;
+ u16 destval,imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ imm = (s8) fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ destval = (*opc83_word_operation[rh]) (*destreg, imm);
+ if (rh != 7)
+ *destreg = destval;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x84
+****************************************************************************/
+void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("TEST\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_byte(destval, *srcreg);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_byte(destval, *srcreg);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_byte(destval, *srcreg);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_byte(*destreg, *srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x85
+****************************************************************************/
+void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("TEST\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_long(destval, *srcreg);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_word(destval, *srcreg);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_long(destval, *srcreg);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_word(destval, *srcreg);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_long(destval, *srcreg);
+ } else {
+ u16 destval;
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_word(destval, *srcreg);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_long(*destreg, *srcreg);
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ test_word(*destreg, *srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x86
+****************************************************************************/
+void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+ u8 destval;
+ u8 tmp;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XCHG\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_byte(destoffset);
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = *destreg;
+ *destreg = tmp;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x87
+****************************************************************************/
+void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XCHG\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg;
+ u32 destval,tmp;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_long(destoffset, destval);
+ } else {
+ u16 *srcreg;
+ u16 destval,tmp;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg;
+ u32 destval,tmp;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_long(destoffset, destval);
+ } else {
+ u16 *srcreg;
+ u16 destval,tmp;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg;
+ u32 destval,tmp;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_long(destoffset);
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_long(destoffset, destval);
+ } else {
+ u16 *srcreg;
+ u16 destval,tmp;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ destval = fetch_data_word(destoffset);
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = destval;
+ destval = tmp;
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+ u32 tmp;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = *destreg;
+ *destreg = tmp;
+ } else {
+ u16 *destreg,*srcreg;
+ u16 tmp;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ tmp = *srcreg;
+ *srcreg = *destreg;
+ *destreg = tmp;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x88
+****************************************************************************/
+void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, *srcreg);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, *srcreg);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, *srcreg);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x89
+****************************************************************************/
+void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_long(destoffset, *srcreg);
+ } else {
+ u16 *srcreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_word(destoffset, *srcreg);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_long(destoffset, *srcreg);
+ } else {
+ u16 *srcreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_word(destoffset, *srcreg);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_long(destoffset, *srcreg);
+ } else {
+ u16 *srcreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ store_data_word(destoffset, *srcreg);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ } else {
+ u16 *destreg,*srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8a
+****************************************************************************/
+void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg, *srcreg;
+ uint srcoffset;
+ u8 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 1:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 2:
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8b
+****************************************************************************/
+void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg, *srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ } else {
+ u16 *destreg, *srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8c
+****************************************************************************/
+void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u16 *destreg, *srcreg;
+ uint destoffset;
+ u16 destval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = *srcreg;
+ store_data_word(destoffset, destval);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = *srcreg;
+ store_data_word(destoffset, destval);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ srcreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = *srcreg;
+ store_data_word(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8d
+****************************************************************************/
+void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u16 *srcreg;
+ uint destoffset;
+
+/*
+ * TODO: Need to handle address size prefix!
+ *
+ * lea eax,[eax+ebx*2] ??
+ */
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LEA\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *srcreg = (u16)destoffset;
+ break;
+ case 1:
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *srcreg = (u16)destoffset;
+ break;
+ case 2:
+ srcreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *srcreg = (u16)destoffset;
+ break;
+ case 3: /* register to register */
+ /* undefined. Do nothing. */
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8e
+****************************************************************************/
+void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u16 *destreg, *srcreg;
+ uint srcoffset;
+ u16 srcval;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 1:
+ destreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 2:
+ destreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 3: /* register to register */
+ destreg = decode_rm_seg_register(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ break;
+ }
+ /*
+ * Clean up, and reset all the R_xSP pointers to the correct
+ * locations. This is about 3x too much overhead (doing all the
+ * segreg ptrs when only one is needed, but this instruction
+ * *cannot* be that common, and this isn't too much work anyway.
+ */
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x8f
+****************************************************************************/
+void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("POP\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (rh != 0) {
+ DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
+ HALT_SYS();
+ }
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = pop_long();
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = pop_word();
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = pop_long();
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = pop_word();
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = pop_long();
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ destval = pop_word();
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = pop_long();
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = pop_word();
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x90
+****************************************************************************/
+void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("NOP\n");
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x91
+****************************************************************************/
+void x86emuOp_xchg_word_AX_CX(u8 X86EMU_UNUSED(op1))
+{
+ u32 tmp;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("XCHG\tEAX,ECX\n");
+ } else {
+ DECODE_PRINTF("XCHG\tAX,CX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ tmp = M.x86.R_EAX;
+ M.x86.R_EAX = M.x86.R_ECX;
+ M.x86.R_ECX = tmp;
+ } else {
+ tmp = M.x86.R_AX;
+ M.x86.R_AX = M.x86.R_CX;
+ M.x86.R_CX = (u16)tmp;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x92
+****************************************************************************/
+void x86emuOp_xchg_word_AX_DX(u8 X86EMU_UNUSED(op1))
+{
+ u32 tmp;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("XCHG\tEAX,EDX\n");
+ } else {
+ DECODE_PRINTF("XCHG\tAX,DX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ tmp = M.x86.R_EAX;
+ M.x86.R_EAX = M.x86.R_EDX;
+ M.x86.R_EDX = tmp;
+ } else {
+ tmp = M.x86.R_AX;
+ M.x86.R_AX = M.x86.R_DX;
+ M.x86.R_DX = (u16)tmp;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x93
+****************************************************************************/
+void x86emuOp_xchg_word_AX_BX(u8 X86EMU_UNUSED(op1))
+{
+ u32 tmp;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("XCHG\tEAX,EBX\n");
+ } else {
+ DECODE_PRINTF("XCHG\tAX,BX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ tmp = M.x86.R_EAX;
+ M.x86.R_EAX = M.x86.R_EBX;
+ M.x86.R_EBX = tmp;
+ } else {
+ tmp = M.x86.R_AX;
+ M.x86.R_AX = M.x86.R_BX;
+ M.x86.R_BX = (u16)tmp;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x94
+****************************************************************************/
+void x86emuOp_xchg_word_AX_SP(u8 X86EMU_UNUSED(op1))
+{
+ u32 tmp;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("XCHG\tEAX,ESP\n");
+ } else {
+ DECODE_PRINTF("XCHG\tAX,SP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ tmp = M.x86.R_EAX;
+ M.x86.R_EAX = M.x86.R_ESP;
+ M.x86.R_ESP = tmp;
+ } else {
+ tmp = M.x86.R_AX;
+ M.x86.R_AX = M.x86.R_SP;
+ M.x86.R_SP = (u16)tmp;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x95
+****************************************************************************/
+void x86emuOp_xchg_word_AX_BP(u8 X86EMU_UNUSED(op1))
+{
+ u32 tmp;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("XCHG\tEAX,EBP\n");
+ } else {
+ DECODE_PRINTF("XCHG\tAX,BP\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ tmp = M.x86.R_EAX;
+ M.x86.R_EAX = M.x86.R_EBP;
+ M.x86.R_EBP = tmp;
+ } else {
+ tmp = M.x86.R_AX;
+ M.x86.R_AX = M.x86.R_BP;
+ M.x86.R_BP = (u16)tmp;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x96
+****************************************************************************/
+void x86emuOp_xchg_word_AX_SI(u8 X86EMU_UNUSED(op1))
+{
+ u32 tmp;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("XCHG\tEAX,ESI\n");
+ } else {
+ DECODE_PRINTF("XCHG\tAX,SI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ tmp = M.x86.R_EAX;
+ M.x86.R_EAX = M.x86.R_ESI;
+ M.x86.R_ESI = tmp;
+ } else {
+ tmp = M.x86.R_AX;
+ M.x86.R_AX = M.x86.R_SI;
+ M.x86.R_SI = (u16)tmp;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x97
+****************************************************************************/
+void x86emuOp_xchg_word_AX_DI(u8 X86EMU_UNUSED(op1))
+{
+ u32 tmp;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("XCHG\tEAX,EDI\n");
+ } else {
+ DECODE_PRINTF("XCHG\tAX,DI\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ tmp = M.x86.R_EAX;
+ M.x86.R_EAX = M.x86.R_EDI;
+ M.x86.R_EDI = tmp;
+ } else {
+ tmp = M.x86.R_AX;
+ M.x86.R_AX = M.x86.R_DI;
+ M.x86.R_DI = (u16)tmp;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x98
+****************************************************************************/
+void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("CWDE\n");
+ } else {
+ DECODE_PRINTF("CBW\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ if (M.x86.R_AX & 0x8000) {
+ M.x86.R_EAX |= 0xffff0000;
+ } else {
+ M.x86.R_EAX &= 0x0000ffff;
+ }
+ } else {
+ if (M.x86.R_AL & 0x80) {
+ M.x86.R_AH = 0xff;
+ } else {
+ M.x86.R_AH = 0x0;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x99
+****************************************************************************/
+void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("CDQ\n");
+ } else {
+ DECODE_PRINTF("CWD\n");
+ }
+ DECODE_PRINTF("CWD\n");
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ if (M.x86.R_EAX & 0x80000000) {
+ M.x86.R_EDX = 0xffffffff;
+ } else {
+ M.x86.R_EDX = 0x0;
+ }
+ } else {
+ if (M.x86.R_AX & 0x8000) {
+ M.x86.R_DX = 0xffff;
+ } else {
+ M.x86.R_DX = 0x0;
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9a
+****************************************************************************/
+void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 farseg, faroff;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CALL\t");
+ faroff = fetch_word_imm();
+ farseg = fetch_word_imm();
+ DECODE_PRINTF2("%04x:", farseg);
+ DECODE_PRINTF2("%04x\n", faroff);
+ CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
+
+ /* XXX
+ *
+ * Hooked interrupt vectors calling into our "BIOS" will cause
+ * problems unless all intersegment stuff is checked for BIOS
+ * access. Check needed here. For moment, let it alone.
+ */
+ TRACE_AND_STEP();
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = farseg;
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = faroff;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9b
+****************************************************************************/
+void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("WAIT");
+ TRACE_AND_STEP();
+ /* NADA. */
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9c
+****************************************************************************/
+void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
+{
+ u32 flags;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("PUSHFD\n");
+ } else {
+ DECODE_PRINTF("PUSHF\n");
+ }
+ TRACE_AND_STEP();
+
+ /* clear out *all* bits not representing flags, and turn on real bits */
+ flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(flags);
+ } else {
+ push_word((u16)flags);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9d
+****************************************************************************/
+void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("POPFD\n");
+ } else {
+ DECODE_PRINTF("POPF\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EFLG = pop_long();
+ } else {
+ M.x86.R_FLG = pop_word();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9e
+****************************************************************************/
+void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("SAHF\n");
+ TRACE_AND_STEP();
+ /* clear the lower bits of the flag register */
+ M.x86.R_FLG &= 0xffffff00;
+ /* or in the AH register into the flags register */
+ M.x86.R_FLG |= M.x86.R_AH;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x9f
+****************************************************************************/
+void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("LAHF\n");
+ TRACE_AND_STEP();
+ M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
+ /*undocumented TC++ behavior??? Nope. It's documented, but
+ you have too look real hard to notice it. */
+ M.x86.R_AH |= 0x2;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa0
+****************************************************************************/
+void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 offset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tAL,");
+ offset = fetch_word_imm();
+ DECODE_PRINTF2("[%04x]\n", offset);
+ TRACE_AND_STEP();
+ M.x86.R_AL = fetch_data_byte(offset);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa1
+****************************************************************************/
+void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 offset;
+
+ START_OF_INSTR();
+ offset = fetch_word_imm();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
+ } else {
+ DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = fetch_data_long(offset);
+ } else {
+ M.x86.R_AX = fetch_data_word(offset);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa2
+****************************************************************************/
+void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 offset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ offset = fetch_word_imm();
+ DECODE_PRINTF2("[%04x],AL\n", offset);
+ TRACE_AND_STEP();
+ store_data_byte(offset, M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa3
+****************************************************************************/
+void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 offset;
+
+ START_OF_INSTR();
+ offset = fetch_word_imm();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
+ } else {
+ DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ store_data_long(offset, M.x86.R_EAX);
+ } else {
+ store_data_word(offset, M.x86.R_AX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa4
+****************************************************************************/
+void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
+{
+ u8 val;
+ u32 count;
+ int inc;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOVS\tBYTE\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -1;
+ else
+ inc = 1;
+ TRACE_AND_STEP();
+ count = 1;
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ count = M.x86.R_CX;
+ M.x86.R_CX = 0;
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ }
+ while (count--) {
+ val = fetch_data_byte(M.x86.R_SI);
+ store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa5
+****************************************************************************/
+void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
+{
+ u32 val;
+ int inc;
+ u32 count;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOVS\tDWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -4;
+ else
+ inc = 4;
+ } else {
+ DECODE_PRINTF("MOVS\tWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -2;
+ else
+ inc = 2;
+ }
+ TRACE_AND_STEP();
+ count = 1;
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ count = M.x86.R_CX;
+ M.x86.R_CX = 0;
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ }
+ while (count--) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val = fetch_data_long(M.x86.R_SI);
+ store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
+ } else {
+ val = fetch_data_word(M.x86.R_SI);
+ store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
+ }
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa6
+****************************************************************************/
+void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
+{
+ s8 val1, val2;
+ int inc;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CMPS\tBYTE\n");
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -1;
+ else
+ inc = 1;
+
+ if (M.x86.mode & SYSMODE_PREFIX_REPE) {
+ /* REPE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ val1 = fetch_data_byte(M.x86.R_SI);
+ val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_byte(val1, val2);
+ M.x86.R_CX -= 1;
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF) == 0)
+ break;
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPE;
+ } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
+ /* REPNE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ val1 = fetch_data_byte(M.x86.R_SI);
+ val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_byte(val1, val2);
+ M.x86.R_CX -= 1;
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF))
+ break; /* zero flag set means equal */
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
+ } else {
+ val1 = fetch_data_byte(M.x86.R_SI);
+ val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_byte(val1, val2);
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa7
+****************************************************************************/
+void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
+{
+ u32 val1,val2;
+ int inc;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("CMPS\tDWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -4;
+ else
+ inc = 4;
+ } else {
+ DECODE_PRINTF("CMPS\tWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -2;
+ else
+ inc = 2;
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_REPE) {
+ /* REPE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val1 = fetch_data_long(M.x86.R_SI);
+ val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_long(val1, val2);
+ } else {
+ val1 = fetch_data_word(M.x86.R_SI);
+ val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_word((u16)val1, (u16)val2);
+ }
+ M.x86.R_CX -= 1;
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF) == 0)
+ break;
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPE;
+ } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
+ /* REPNE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val1 = fetch_data_long(M.x86.R_SI);
+ val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_long(val1, val2);
+ } else {
+ val1 = fetch_data_word(M.x86.R_SI);
+ val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_word((u16)val1, (u16)val2);
+ }
+ M.x86.R_CX -= 1;
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF))
+ break; /* zero flag set means equal */
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
+ } else {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val1 = fetch_data_long(M.x86.R_SI);
+ val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_long(val1, val2);
+ } else {
+ val1 = fetch_data_word(M.x86.R_SI);
+ val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_word((u16)val1, (u16)val2);
+ }
+ M.x86.R_SI += inc;
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa8
+****************************************************************************/
+void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("TEST\tAL,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%04x\n", imm);
+ TRACE_AND_STEP();
+ test_byte(M.x86.R_AL, (u8)imm);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xa9
+****************************************************************************/
+void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("TEST\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("TEST\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ test_long(M.x86.R_EAX, srcval);
+ } else {
+ test_word(M.x86.R_AX, (u16)srcval);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xaa
+****************************************************************************/
+void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
+{
+ int inc;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("STOS\tBYTE\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -1;
+ else
+ inc = 1;
+ TRACE_AND_STEP();
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
+ M.x86.R_CX -= 1;
+ M.x86.R_DI += inc;
+ }
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ } else {
+ store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xab
+****************************************************************************/
+void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
+{
+ int inc;
+ u32 count;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("STOS\tDWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -4;
+ else
+ inc = 4;
+ } else {
+ DECODE_PRINTF("STOS\tWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -2;
+ else
+ inc = 2;
+ }
+ TRACE_AND_STEP();
+ count = 1;
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ count = M.x86.R_CX;
+ M.x86.R_CX = 0;
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ }
+ while (count--) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
+ } else {
+ store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
+ }
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xac
+****************************************************************************/
+void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
+{
+ int inc;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LODS\tBYTE\n");
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -1;
+ else
+ inc = 1;
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
+ M.x86.R_CX -= 1;
+ M.x86.R_SI += inc;
+ }
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ } else {
+ M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
+ M.x86.R_SI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xad
+****************************************************************************/
+void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
+{
+ int inc;
+ u32 count;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("LODS\tDWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -4;
+ else
+ inc = 4;
+ } else {
+ DECODE_PRINTF("LODS\tWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -2;
+ else
+ inc = 2;
+ }
+ TRACE_AND_STEP();
+ count = 1;
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* move them until CX is ZERO. */
+ count = M.x86.R_CX;
+ M.x86.R_CX = 0;
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ }
+ while (count--) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
+ } else {
+ M.x86.R_AX = fetch_data_word(M.x86.R_SI);
+ }
+ M.x86.R_SI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xae
+****************************************************************************/
+void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
+{
+ s8 val2;
+ int inc;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SCAS\tBYTE\n");
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -1;
+ else
+ inc = 1;
+ if (M.x86.mode & SYSMODE_PREFIX_REPE) {
+ /* REPE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_byte(M.x86.R_AL, val2);
+ M.x86.R_CX -= 1;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF) == 0)
+ break;
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPE;
+ } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
+ /* REPNE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_byte(M.x86.R_AL, val2);
+ M.x86.R_CX -= 1;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF))
+ break; /* zero flag set means equal */
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
+ } else {
+ val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_byte(M.x86.R_AL, val2);
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xaf
+****************************************************************************/
+void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
+{
+ int inc;
+ u32 val;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("SCAS\tDWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -4;
+ else
+ inc = 4;
+ } else {
+ DECODE_PRINTF("SCAS\tWORD\n");
+ if (ACCESS_FLAG(F_DF)) /* down */
+ inc = -2;
+ else
+ inc = 2;
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_REPE) {
+ /* REPE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_long(M.x86.R_EAX, val);
+ } else {
+ val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_word(M.x86.R_AX, (u16)val);
+ }
+ M.x86.R_CX -= 1;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF) == 0)
+ break;
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPE;
+ } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
+ /* REPNE */
+ /* move them until CX is ZERO. */
+ while (M.x86.R_CX != 0) {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_long(M.x86.R_EAX, val);
+ } else {
+ val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_word(M.x86.R_AX, (u16)val);
+ }
+ M.x86.R_CX -= 1;
+ M.x86.R_DI += inc;
+ if (ACCESS_FLAG(F_ZF))
+ break; /* zero flag set means equal */
+ }
+ M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
+ } else {
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_long(M.x86.R_EAX, val);
+ } else {
+ val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
+ cmp_word(M.x86.R_AX, (u16)val);
+ }
+ M.x86.R_DI += inc;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb0
+****************************************************************************/
+void x86emuOp_mov_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tAL,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ M.x86.R_AL = imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb1
+****************************************************************************/
+void x86emuOp_mov_byte_CL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tCL,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ M.x86.R_CL = imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb2
+****************************************************************************/
+void x86emuOp_mov_byte_DL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tDL,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ M.x86.R_DL = imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb3
+****************************************************************************/
+void x86emuOp_mov_byte_BL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tBL,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ M.x86.R_BL = imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb4
+****************************************************************************/
+void x86emuOp_mov_byte_AH_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tAH,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ M.x86.R_AH = imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb5
+****************************************************************************/
+void x86emuOp_mov_byte_CH_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tCH,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ M.x86.R_CH = imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb6
+****************************************************************************/
+void x86emuOp_mov_byte_DH_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tDH,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ M.x86.R_DH = imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb7
+****************************************************************************/
+void x86emuOp_mov_byte_BH_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\tBH,");
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ TRACE_AND_STEP();
+ M.x86.R_BH = imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb8
+****************************************************************************/
+void x86emuOp_mov_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOV\tEAX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("MOV\tAX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = srcval;
+ } else {
+ M.x86.R_AX = (u16)srcval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xb9
+****************************************************************************/
+void x86emuOp_mov_word_CX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOV\tECX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("MOV\tCX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ECX = srcval;
+ } else {
+ M.x86.R_CX = (u16)srcval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xba
+****************************************************************************/
+void x86emuOp_mov_word_DX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOV\tEDX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("MOV\tDX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDX = srcval;
+ } else {
+ M.x86.R_DX = (u16)srcval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xbb
+****************************************************************************/
+void x86emuOp_mov_word_BX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOV\tEBX,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("MOV\tBX,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EBX = srcval;
+ } else {
+ M.x86.R_BX = (u16)srcval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xbc
+****************************************************************************/
+void x86emuOp_mov_word_SP_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOV\tESP,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("MOV\tSP,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ESP = srcval;
+ } else {
+ M.x86.R_SP = (u16)srcval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xbd
+****************************************************************************/
+void x86emuOp_mov_word_BP_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOV\tEBP,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("MOV\tBP,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EBP = srcval;
+ } else {
+ M.x86.R_BP = (u16)srcval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xbe
+****************************************************************************/
+void x86emuOp_mov_word_SI_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOV\tESI,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("MOV\tSI,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ESI = srcval;
+ } else {
+ M.x86.R_SI = (u16)srcval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xbf
+****************************************************************************/
+void x86emuOp_mov_word_DI_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u32 srcval;
+
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("MOV\tEDI,");
+ srcval = fetch_long_imm();
+ } else {
+ DECODE_PRINTF("MOV\tDI,");
+ srcval = fetch_word_imm();
+ }
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EDI = srcval;
+ } else {
+ M.x86.R_DI = (u16)srcval;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/* used by opcodes c0, d0, and d2. */
+static u8(*opcD0_byte_operation[])(u8 d, u8 s) =
+{
+ rol_byte,
+ ror_byte,
+ rcl_byte,
+ rcr_byte,
+ shl_byte,
+ shr_byte,
+ shl_byte, /* sal_byte === shl_byte by definition */
+ sar_byte,
+};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc0
+****************************************************************************/
+void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 destval;
+ u8 amt;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ switch (mod) {
+ case 0:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, amt);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, amt);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, amt);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
+ *destreg = destval;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/* used by opcodes c1, d1, and d3. */
+static u16(*opcD1_word_operation[])(u16 s, u8 d) =
+{
+ rol_word,
+ ror_word,
+ rcl_word,
+ rcr_word,
+ shl_word,
+ shr_word,
+ shl_word, /* sal_byte === shl_byte by definition */
+ sar_word,
+};
+
+/* used by opcodes c1, d1, and d3. */
+static u32 (*opcD1_long_operation[])(u32 s, u8 d) =
+{
+ rol_long,
+ ror_long,
+ rcl_long,
+ rcr_long,
+ shl_long,
+ shr_long,
+ shl_long, /* sal_byte === shl_byte by definition */
+ sar_long,
+};
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc1
+****************************************************************************/
+void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 amt;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, amt);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, amt);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, amt);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, amt);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, amt);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, amt);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ TRACE_AND_STEP();
+ *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ amt = fetch_byte_imm();
+ DECODE_PRINTF2(",%x\n", amt);
+ TRACE_AND_STEP();
+ *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc2
+****************************************************************************/
+void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("RET\t");
+ imm = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = pop_word();
+ M.x86.R_SP += imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc3
+****************************************************************************/
+void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("RET\n");
+ RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc4
+****************************************************************************/
+void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rh, rl;
+ u16 *dstreg;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LES\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_ES = fetch_data_word(srcoffset + 2);
+ break;
+ case 1:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_ES = fetch_data_word(srcoffset + 2);
+ break;
+ case 2:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_ES = fetch_data_word(srcoffset + 2);
+ break;
+ case 3: /* register to register */
+ /* UNDEFINED! */
+ TRACE_AND_STEP();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc5
+****************************************************************************/
+void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rh, rl;
+ u16 *dstreg;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LDS\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_DS = fetch_data_word(srcoffset + 2);
+ break;
+ case 1:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_DS = fetch_data_word(srcoffset + 2);
+ break;
+ case 2:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_DS = fetch_data_word(srcoffset + 2);
+ break;
+ case 3: /* register to register */
+ /* UNDEFINED! */
+ TRACE_AND_STEP();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc6
+****************************************************************************/
+void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (rh != 0) {
+ DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
+ HALT_SYS();
+ }
+ switch (mod) {
+ case 0:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%2x\n", imm);
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, imm);
+ break;
+ case 1:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%2x\n", imm);
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, imm);
+ break;
+ case 2:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%2x\n", imm);
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, imm);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ imm = fetch_byte_imm();
+ DECODE_PRINTF2(",%2x\n", imm);
+ TRACE_AND_STEP();
+ *destreg = imm;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc7
+****************************************************************************/
+void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOV\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ if (rh != 0) {
+ DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
+ HALT_SYS();
+ }
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ store_data_long(destoffset, imm);
+ } else {
+ u16 imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ store_data_word(destoffset, imm);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ store_data_long(destoffset, imm);
+ } else {
+ u16 imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ store_data_word(destoffset, imm);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 imm;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ store_data_long(destoffset, imm);
+ } else {
+ u16 imm;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ store_data_word(destoffset, imm);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 imm;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ imm = fetch_long_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ *destreg = imm;
+ } else {
+ u16 *destreg;
+ u16 imm;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ imm = fetch_word_imm();
+ DECODE_PRINTF2(",%x\n", imm);
+ TRACE_AND_STEP();
+ *destreg = imm;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc8
+****************************************************************************/
+void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
+{
+ u16 local,frame_pointer;
+ u8 nesting;
+ int i;
+
+ START_OF_INSTR();
+ local = fetch_word_imm();
+ nesting = fetch_byte_imm();
+ DECODE_PRINTF2("ENTER %x\n", local);
+ DECODE_PRINTF2(",%x\n", nesting);
+ TRACE_AND_STEP();
+ push_word(M.x86.R_BP);
+ frame_pointer = M.x86.R_SP;
+ if (nesting > 0) {
+ for (i = 1; i < nesting; i++) {
+ M.x86.R_BP -= 2;
+ push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
+ }
+ push_word(frame_pointer);
+ }
+ M.x86.R_BP = frame_pointer;
+ M.x86.R_SP = (u16)(M.x86.R_SP - local);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xc9
+****************************************************************************/
+void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("LEAVE\n");
+ TRACE_AND_STEP();
+ M.x86.R_SP = M.x86.R_BP;
+ M.x86.R_BP = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xca
+****************************************************************************/
+void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 imm;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("RETF\t");
+ imm = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", imm);
+ RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = pop_word();
+ M.x86.R_CS = pop_word();
+ M.x86.R_SP += imm;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcb
+****************************************************************************/
+void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("RETF\n");
+ RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = pop_word();
+ M.x86.R_CS = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcc
+****************************************************************************/
+void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
+{
+ u16 tmp;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("INT 3\n");
+ tmp = (u16) mem_access_word(3 * 4 + 2);
+ /* access the segment register */
+ TRACE_AND_STEP();
+ if (_X86EMU_intrTab[3]) {
+ (*_X86EMU_intrTab[3])(3);
+ } else {
+ push_word((u16)M.x86.R_FLG);
+ CLEAR_FLAG(F_IF);
+ CLEAR_FLAG(F_TF);
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = mem_access_word(3 * 4 + 2);
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = mem_access_word(3 * 4);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcd
+****************************************************************************/
+void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 tmp;
+ u8 intnum;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("INT\t");
+ intnum = fetch_byte_imm();
+ DECODE_PRINTF2("%x\n", intnum);
+ tmp = mem_access_word(intnum * 4 + 2);
+ TRACE_AND_STEP();
+ if (_X86EMU_intrTab[intnum]) {
+ (*_X86EMU_intrTab[intnum])(intnum);
+ } else {
+ push_word((u16)M.x86.R_FLG);
+ CLEAR_FLAG(F_IF);
+ CLEAR_FLAG(F_TF);
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = mem_access_word(intnum * 4 + 2);
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = mem_access_word(intnum * 4);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xce
+****************************************************************************/
+void x86emuOp_into(u8 X86EMU_UNUSED(op1))
+{
+ u16 tmp;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("INTO\n");
+ TRACE_AND_STEP();
+ if (ACCESS_FLAG(F_OF)) {
+ tmp = mem_access_word(4 * 4 + 2);
+ if (_X86EMU_intrTab[4]) {
+ (*_X86EMU_intrTab[4])(4);
+ } else {
+ push_word((u16)M.x86.R_FLG);
+ CLEAR_FLAG(F_IF);
+ CLEAR_FLAG(F_TF);
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = mem_access_word(4 * 4 + 2);
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = mem_access_word(4 * 4);
+ }
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xcf
+****************************************************************************/
+void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("IRET\n");
+
+ TRACE_AND_STEP();
+
+ M.x86.R_IP = pop_word();
+ M.x86.R_CS = pop_word();
+ M.x86.R_FLG = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd0
+****************************************************************************/
+void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 destval;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ switch (mod) {
+ case 0:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, 1);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, 1);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, 1);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",1\n");
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
+ *destreg = destval;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd1
+****************************************************************************/
+void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, 1);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, 1);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, 1);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, 1);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, 1);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",1\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, 1);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",1\n");
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (*destreg, 1);
+ *destreg = destval;
+ } else {
+ u16 destval;
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",1\n");
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (*destreg, 1);
+ *destreg = destval;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd2
+****************************************************************************/
+void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 destval;
+ u8 amt;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ amt = M.x86.R_CL;
+ switch (mod) {
+ case 0:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, amt);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, amt);
+ store_data_byte(destoffset, destval);
+ break;
+ case 2:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (destval, amt);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
+ *destreg = destval;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd3
+****************************************************************************/
+void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 amt;
+
+ /*
+ * Yet another weirdo special case instruction format. Part of
+ * the opcode held below in "RH". Doubly nested case would
+ * result, except that the decoded instruction
+ */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("ROL\t");
+ break;
+ case 1:
+ DECODE_PRINTF("ROR\t");
+ break;
+ case 2:
+ DECODE_PRINTF("RCL\t");
+ break;
+ case 3:
+ DECODE_PRINTF("RCR\t");
+ break;
+ case 4:
+ DECODE_PRINTF("SHL\t");
+ break;
+ case 5:
+ DECODE_PRINTF("SHR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("SAL\t");
+ break;
+ case 7:
+ DECODE_PRINTF("SAR\t");
+ break;
+ }
+ }
+#endif
+ /* know operation, decode the mod byte to find the addressing
+ mode. */
+ amt = M.x86.R_CL;
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, amt);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, amt);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, amt);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, amt);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_long_operation[rh]) (destval, amt);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("WORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",CL\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = (*opcD1_word_operation[rh]) (destval, amt);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd4
+****************************************************************************/
+void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
+{
+ u8 a;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("AAM\n");
+ a = fetch_byte_imm(); /* this is a stupid encoding. */
+ if (a != 10) {
+ DECODE_PRINTF("ERROR DECODING AAM\n");
+ TRACE_REGS();
+ HALT_SYS();
+ }
+ TRACE_AND_STEP();
+ /* note the type change here --- returning AL and AH in AX. */
+ M.x86.R_AX = aam_word(M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd5
+****************************************************************************/
+void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
+{
+ u8 a;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("AAD\n");
+ a = fetch_byte_imm();
+ TRACE_AND_STEP();
+ M.x86.R_AX = aad_word(M.x86.R_AX);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/* opcode 0xd6 ILLEGAL OPCODE */
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xd7
+****************************************************************************/
+void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
+{
+ u16 addr;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("XLAT\n");
+ TRACE_AND_STEP();
+ addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
+ M.x86.R_AL = fetch_data_byte(addr);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/* instuctions D8 .. DF are in i87_ops.c */
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe0
+****************************************************************************/
+void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
+{
+ s16 ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LOOPNE\t");
+ ip = (s8) fetch_byte_imm();
+ ip += (s16) M.x86.R_IP;
+ DECODE_PRINTF2("%04x\n", ip);
+ TRACE_AND_STEP();
+ M.x86.R_CX -= 1;
+ if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
+ M.x86.R_IP = ip;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe1
+****************************************************************************/
+void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
+{
+ s16 ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LOOPE\t");
+ ip = (s8) fetch_byte_imm();
+ ip += (s16) M.x86.R_IP;
+ DECODE_PRINTF2("%04x\n", ip);
+ TRACE_AND_STEP();
+ M.x86.R_CX -= 1;
+ if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
+ M.x86.R_IP = ip;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe2
+****************************************************************************/
+void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
+{
+ s16 ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LOOP\t");
+ ip = (s8) fetch_byte_imm();
+ ip += (s16) M.x86.R_IP;
+ DECODE_PRINTF2("%04x\n", ip);
+ TRACE_AND_STEP();
+ M.x86.R_CX -= 1;
+ if (M.x86.R_CX != 0)
+ M.x86.R_IP = ip;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe3
+****************************************************************************/
+void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
+{
+ u16 target;
+ s8 offset;
+
+ /* jump to byte offset if overflow flag is set */
+ START_OF_INSTR();
+ DECODE_PRINTF("JCXZ\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ if (M.x86.R_CX == 0)
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe4
+****************************************************************************/
+void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 port;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("IN\t");
+ port = (u8) fetch_byte_imm();
+ DECODE_PRINTF2("%x,AL\n", port);
+ TRACE_AND_STEP();
+ M.x86.R_AL = (*sys_inb)(port);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe5
+****************************************************************************/
+void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u8 port;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("IN\t");
+ port = (u8) fetch_byte_imm();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF2("EAX,%x\n", port);
+ } else {
+ DECODE_PRINTF2("AX,%x\n", port);
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = (*sys_inl)(port);
+ } else {
+ M.x86.R_AX = (*sys_inw)(port);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe6
+****************************************************************************/
+void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
+{
+ u8 port;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("OUT\t");
+ port = (u8) fetch_byte_imm();
+ DECODE_PRINTF2("%x,AL\n", port);
+ TRACE_AND_STEP();
+ (*sys_outb)(port, M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe7
+****************************************************************************/
+void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
+{
+ u8 port;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("OUT\t");
+ port = (u8) fetch_byte_imm();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF2("%x,EAX\n", port);
+ } else {
+ DECODE_PRINTF2("%x,AX\n", port);
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ (*sys_outl)(port, M.x86.R_EAX);
+ } else {
+ (*sys_outw)(port, M.x86.R_AX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe8
+****************************************************************************/
+void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
+{
+ s16 ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("CALL\t");
+ ip = (s16) fetch_word_imm();
+ ip += (s16) M.x86.R_IP; /* CHECK SIGN */
+ DECODE_PRINTF2("%04x\n", ip);
+ CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = ip;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xe9
+****************************************************************************/
+void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
+{
+ int ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("JMP\t");
+ ip = (s16)fetch_word_imm();
+ ip += (s16)M.x86.R_IP;
+ DECODE_PRINTF2("%04x\n", ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = (u16)ip;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xea
+****************************************************************************/
+void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 cs, ip;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("JMP\tFAR ");
+ ip = fetch_word_imm();
+ cs = fetch_word_imm();
+ DECODE_PRINTF2("%04x:", cs);
+ DECODE_PRINTF2("%04x\n", ip);
+ TRACE_AND_STEP();
+ M.x86.R_IP = ip;
+ M.x86.R_CS = cs;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xeb
+****************************************************************************/
+void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
+{
+ u16 target;
+ s8 offset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("JMP\t");
+ offset = (s8)fetch_byte_imm();
+ target = (u16)(M.x86.R_IP + offset);
+ DECODE_PRINTF2("%x\n", target);
+ TRACE_AND_STEP();
+ M.x86.R_IP = target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xec
+****************************************************************************/
+void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("IN\tAL,DX\n");
+ TRACE_AND_STEP();
+ M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xed
+****************************************************************************/
+void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("IN\tEAX,DX\n");
+ } else {
+ DECODE_PRINTF("IN\tAX,DX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
+ } else {
+ M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xee
+****************************************************************************/
+void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("OUT\tDX,AL\n");
+ TRACE_AND_STEP();
+ (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xef
+****************************************************************************/
+void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("OUT\tDX,EAX\n");
+ } else {
+ DECODE_PRINTF("OUT\tDX,AX\n");
+ }
+ TRACE_AND_STEP();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
+ } else {
+ (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf0
+****************************************************************************/
+void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("LOCK:\n");
+ TRACE_AND_STEP();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/*opcode 0xf1 ILLEGAL OPERATION */
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf2
+****************************************************************************/
+void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("REPNE\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_PREFIX_REPNE;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf3
+****************************************************************************/
+void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("REPE\n");
+ TRACE_AND_STEP();
+ M.x86.mode |= SYSMODE_PREFIX_REPE;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf4
+****************************************************************************/
+void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("HALT\n");
+ TRACE_AND_STEP();
+ HALT_SYS();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf5
+****************************************************************************/
+void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
+{
+ /* complement the carry flag. */
+ START_OF_INSTR();
+ DECODE_PRINTF("CMC\n");
+ TRACE_AND_STEP();
+ TOGGLE_FLAG(F_CF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf6
+****************************************************************************/
+void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ u8 *destreg;
+ uint destoffset;
+ u8 destval, srcval;
+
+ /* long, drawn out code follows. Double switch for a total
+ of 32 cases. */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0: /* mod=00 */
+ switch (rh) {
+ case 0: /* test byte imm */
+ DECODE_PRINTF("TEST\tBYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%02x\n", srcval);
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ test_byte(destval, srcval);
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ DECODE_PRINTF("NOT\tBYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = not_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3:
+ DECODE_PRINTF("NEG\tBYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 4:
+ DECODE_PRINTF("MUL\tBYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ mul_byte(destval);
+ break;
+ case 5:
+ DECODE_PRINTF("IMUL\tBYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ imul_byte(destval);
+ break;
+ case 6:
+ DECODE_PRINTF("DIV\tBYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ div_byte(destval);
+ break;
+ case 7:
+ DECODE_PRINTF("IDIV\tBYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ idiv_byte(destval);
+ break;
+ }
+ break; /* end mod==00 */
+ case 1: /* mod=01 */
+ switch (rh) {
+ case 0: /* test byte imm */
+ DECODE_PRINTF("TEST\tBYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%02x\n", srcval);
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ test_byte(destval, srcval);
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=01 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ DECODE_PRINTF("NOT\tBYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = not_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3:
+ DECODE_PRINTF("NEG\tBYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 4:
+ DECODE_PRINTF("MUL\tBYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ mul_byte(destval);
+ break;
+ case 5:
+ DECODE_PRINTF("IMUL\tBYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ imul_byte(destval);
+ break;
+ case 6:
+ DECODE_PRINTF("DIV\tBYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ div_byte(destval);
+ break;
+ case 7:
+ DECODE_PRINTF("IDIV\tBYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ idiv_byte(destval);
+ break;
+ }
+ break; /* end mod==01 */
+ case 2: /* mod=10 */
+ switch (rh) {
+ case 0: /* test byte imm */
+ DECODE_PRINTF("TEST\tBYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%02x\n", srcval);
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ test_byte(destval, srcval);
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=10 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ DECODE_PRINTF("NOT\tBYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = not_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 3:
+ DECODE_PRINTF("NEG\tBYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 4:
+ DECODE_PRINTF("MUL\tBYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ mul_byte(destval);
+ break;
+ case 5:
+ DECODE_PRINTF("IMUL\tBYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ imul_byte(destval);
+ break;
+ case 6:
+ DECODE_PRINTF("DIV\tBYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ div_byte(destval);
+ break;
+ case 7:
+ DECODE_PRINTF("IDIV\tBYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ idiv_byte(destval);
+ break;
+ }
+ break; /* end mod==10 */
+ case 3: /* mod=11 */
+ switch (rh) {
+ case 0: /* test byte imm */
+ DECODE_PRINTF("TEST\t");
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_byte_imm();
+ DECODE_PRINTF2("%02x\n", srcval);
+ TRACE_AND_STEP();
+ test_byte(*destreg, srcval);
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ DECODE_PRINTF("NOT\t");
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = not_byte(*destreg);
+ break;
+ case 3:
+ DECODE_PRINTF("NEG\t");
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = neg_byte(*destreg);
+ break;
+ case 4:
+ DECODE_PRINTF("MUL\t");
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ mul_byte(*destreg); /*!!! */
+ break;
+ case 5:
+ DECODE_PRINTF("IMUL\t");
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ imul_byte(*destreg);
+ break;
+ case 6:
+ DECODE_PRINTF("DIV\t");
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ div_byte(*destreg);
+ break;
+ case 7:
+ DECODE_PRINTF("IDIV\t");
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ idiv_byte(*destreg);
+ break;
+ }
+ break; /* end mod==11 */
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf7
+****************************************************************************/
+void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ /* long, drawn out code follows. Double switch for a total
+ of 32 cases. */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0: /* mod=00 */
+ switch (rh) {
+ case 0: /* test word imm */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,srcval;
+
+ DECODE_PRINTF("TEST\tDWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ test_long(destval, srcval);
+ } else {
+ u16 destval,srcval;
+
+ DECODE_PRINTF("TEST\tWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ test_word(destval, srcval);
+ }
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
+ HALT_SYS();
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("NOT\tDWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = not_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("NOT\tWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = not_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("NEG\tDWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("NEG\tWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 4:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("MUL\tDWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ mul_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("MUL\tWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ mul_word(destval);
+ }
+ break;
+ case 5:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("IMUL\tDWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ imul_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("IMUL\tWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ imul_word(destval);
+ }
+ break;
+ case 6:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DIV\tDWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ div_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("DIV\tWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ div_word(destval);
+ }
+ break;
+ case 7:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("IDIV\tDWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ idiv_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("IDIV\tWORD PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ idiv_word(destval);
+ }
+ break;
+ }
+ break; /* end mod==00 */
+ case 1: /* mod=01 */
+ switch (rh) {
+ case 0: /* test word imm */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,srcval;
+
+ DECODE_PRINTF("TEST\tDWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ test_long(destval, srcval);
+ } else {
+ u16 destval,srcval;
+
+ DECODE_PRINTF("TEST\tWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ test_word(destval, srcval);
+ }
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=01 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("NOT\tDWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = not_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("NOT\tWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = not_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("NEG\tDWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("NEG\tWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 4:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("MUL\tDWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ mul_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("MUL\tWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ mul_word(destval);
+ }
+ break;
+ case 5:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("IMUL\tDWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ imul_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("IMUL\tWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ imul_word(destval);
+ }
+ break;
+ case 6:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DIV\tDWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ div_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("DIV\tWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ div_word(destval);
+ }
+ break;
+ case 7:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("IDIV\tDWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ idiv_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("IDIV\tWORD PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ idiv_word(destval);
+ }
+ break;
+ }
+ break; /* end mod==01 */
+ case 2: /* mod=10 */
+ switch (rh) {
+ case 0: /* test word imm */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval,srcval;
+
+ DECODE_PRINTF("TEST\tDWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ test_long(destval, srcval);
+ } else {
+ u16 destval,srcval;
+
+ DECODE_PRINTF("TEST\tWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ test_word(destval, srcval);
+ }
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=10 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("NOT\tDWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = not_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("NOT\tWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = not_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("NEG\tDWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("NEG\tWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = neg_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 4:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("MUL\tDWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ mul_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("MUL\tWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ mul_word(destval);
+ }
+ break;
+ case 5:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("IMUL\tDWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ imul_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("IMUL\tWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ imul_word(destval);
+ }
+ break;
+ case 6:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("DIV\tDWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ div_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("DIV\tWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ div_word(destval);
+ }
+ break;
+ case 7:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ DECODE_PRINTF("IDIV\tDWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ idiv_long(destval);
+ } else {
+ u16 destval;
+
+ DECODE_PRINTF("IDIV\tWORD PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ idiv_word(destval);
+ }
+ break;
+ }
+ break; /* end mod==10 */
+ case 3: /* mod=11 */
+ switch (rh) {
+ case 0: /* test word imm */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ DECODE_PRINTF("TEST\t");
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_long_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ test_long(*destreg, srcval);
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ DECODE_PRINTF("TEST\t");
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ srcval = fetch_word_imm();
+ DECODE_PRINTF2("%x\n", srcval);
+ TRACE_AND_STEP();
+ test_word(*destreg, srcval);
+ }
+ break;
+ case 1:
+ DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
+ HALT_SYS();
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ DECODE_PRINTF("NOT\t");
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = not_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ DECODE_PRINTF("NOT\t");
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = not_word(*destreg);
+ }
+ break;
+ case 3:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ DECODE_PRINTF("NEG\t");
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = neg_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ DECODE_PRINTF("NEG\t");
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = neg_word(*destreg);
+ }
+ break;
+ case 4:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ DECODE_PRINTF("MUL\t");
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ mul_long(*destreg); /*!!! */
+ } else {
+ u16 *destreg;
+
+ DECODE_PRINTF("MUL\t");
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ mul_word(*destreg); /*!!! */
+ }
+ break;
+ case 5:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ DECODE_PRINTF("IMUL\t");
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ imul_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ DECODE_PRINTF("IMUL\t");
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ imul_word(*destreg);
+ }
+ break;
+ case 6:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ DECODE_PRINTF("DIV\t");
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ div_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ DECODE_PRINTF("DIV\t");
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ div_word(*destreg);
+ }
+ break;
+ case 7:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ DECODE_PRINTF("IDIV\t");
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ idiv_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ DECODE_PRINTF("IDIV\t");
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ idiv_word(*destreg);
+ }
+ break;
+ }
+ break; /* end mod==11 */
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf8
+****************************************************************************/
+void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
+{
+ /* clear the carry flag. */
+ START_OF_INSTR();
+ DECODE_PRINTF("CLC\n");
+ TRACE_AND_STEP();
+ CLEAR_FLAG(F_CF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xf9
+****************************************************************************/
+void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
+{
+ /* set the carry flag. */
+ START_OF_INSTR();
+ DECODE_PRINTF("STC\n");
+ TRACE_AND_STEP();
+ SET_FLAG(F_CF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfa
+****************************************************************************/
+void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
+{
+ /* clear interrupts. */
+ START_OF_INSTR();
+ DECODE_PRINTF("CLI\n");
+ TRACE_AND_STEP();
+ CLEAR_FLAG(F_IF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfb
+****************************************************************************/
+void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
+{
+ /* enable interrupts. */
+ START_OF_INSTR();
+ DECODE_PRINTF("STI\n");
+ TRACE_AND_STEP();
+ SET_FLAG(F_IF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfc
+****************************************************************************/
+void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
+{
+ /* clear interrupts. */
+ START_OF_INSTR();
+ DECODE_PRINTF("CLD\n");
+ TRACE_AND_STEP();
+ CLEAR_FLAG(F_DF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfd
+****************************************************************************/
+void x86emuOp_std(u8 X86EMU_UNUSED(op1))
+{
+ /* clear interrupts. */
+ START_OF_INSTR();
+ DECODE_PRINTF("STD\n");
+ TRACE_AND_STEP();
+ SET_FLAG(F_DF);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xfe
+****************************************************************************/
+void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rh, rl;
+ u8 destval;
+ uint destoffset;
+ u8 *destreg;
+
+ /* Yet another special case instruction. */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ DECODE_PRINTF("INC\t");
+ break;
+ case 1:
+ DECODE_PRINTF("DEC\t");
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
+ HALT_SYS();
+ break;
+ }
+ }
+#endif
+ switch (mod) {
+ case 0:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ switch (rh) {
+ case 0: /* inc word ptr ... */
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1: /* dec word ptr ... */
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ }
+ break;
+ case 1:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ switch (rh) {
+ case 0:
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ }
+ break;
+ case 2:
+ DECODE_PRINTF("BYTE PTR ");
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ switch (rh) {
+ case 0:
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ case 1:
+ destval = fetch_data_byte(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_byte(destval);
+ store_data_byte(destoffset, destval);
+ break;
+ }
+ break;
+ case 3:
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ switch (rh) {
+ case 0:
+ TRACE_AND_STEP();
+ *destreg = inc_byte(*destreg);
+ break;
+ case 1:
+ TRACE_AND_STEP();
+ *destreg = dec_byte(*destreg);
+ break;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0xff
+****************************************************************************/
+void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
+{
+ int mod, rh, rl;
+ uint destoffset = 0;
+ u16 *destreg;
+ u16 destval,destval2;
+
+ /* Yet another special case instruction. */
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+#ifdef DEBUG
+ if (DEBUG_DECODE()) {
+ /* XXX DECODE_PRINTF may be changed to something more
+ general, so that it is important to leave the strings
+ in the same format, even though the result is that the
+ above test is done twice. */
+
+ switch (rh) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("INC\tDWORD PTR ");
+ } else {
+ DECODE_PRINTF("INC\tWORD PTR ");
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ DECODE_PRINTF("DEC\tDWORD PTR ");
+ } else {
+ DECODE_PRINTF("DEC\tWORD PTR ");
+ }
+ break;
+ case 2:
+ DECODE_PRINTF("CALL\t ");
+ break;
+ case 3:
+ DECODE_PRINTF("CALL\tFAR ");
+ break;
+ case 4:
+ DECODE_PRINTF("JMP\t");
+ break;
+ case 5:
+ DECODE_PRINTF("JMP\tFAR ");
+ break;
+ case 6:
+ DECODE_PRINTF("PUSH\t");
+ break;
+ case 7:
+ DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
+ HALT_SYS();
+ break;
+ }
+ }
+#endif
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ switch (rh) {
+ case 0: /* inc word ptr ... */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1: /* dec word ptr ... */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2: /* call word ptr ... */
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = destval;
+ break;
+ case 3: /* call far ptr ... */
+ destval = fetch_data_word(destoffset);
+ destval2 = fetch_data_word(destoffset + 2);
+ TRACE_AND_STEP();
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = destval2;
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = destval;
+ break;
+ case 4: /* jmp word ptr ... */
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ M.x86.R_IP = destval;
+ break;
+ case 5: /* jmp far ptr ... */
+ destval = fetch_data_word(destoffset);
+ destval2 = fetch_data_word(destoffset + 2);
+ TRACE_AND_STEP();
+ M.x86.R_IP = destval;
+ M.x86.R_CS = destval2;
+ break;
+ case 6: /* push word ptr ... */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ push_long(destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ push_word(destval);
+ }
+ break;
+ }
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ switch (rh) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2: /* call word ptr ... */
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = destval;
+ break;
+ case 3: /* call far ptr ... */
+ destval = fetch_data_word(destoffset);
+ destval2 = fetch_data_word(destoffset + 2);
+ TRACE_AND_STEP();
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = destval2;
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = destval;
+ break;
+ case 4: /* jmp word ptr ... */
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ M.x86.R_IP = destval;
+ break;
+ case 5: /* jmp far ptr ... */
+ destval = fetch_data_word(destoffset);
+ destval2 = fetch_data_word(destoffset + 2);
+ TRACE_AND_STEP();
+ M.x86.R_IP = destval;
+ M.x86.R_CS = destval2;
+ break;
+ case 6: /* push word ptr ... */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ push_long(destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ push_word(destval);
+ }
+ break;
+ }
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ switch (rh) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = inc_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_long(destval);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ destval = dec_word(destval);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2: /* call word ptr ... */
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = destval;
+ break;
+ case 3: /* call far ptr ... */
+ destval = fetch_data_word(destoffset);
+ destval2 = fetch_data_word(destoffset + 2);
+ TRACE_AND_STEP();
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = destval2;
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = destval;
+ break;
+ case 4: /* jmp word ptr ... */
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ M.x86.R_IP = destval;
+ break;
+ case 5: /* jmp far ptr ... */
+ destval = fetch_data_word(destoffset);
+ destval2 = fetch_data_word(destoffset + 2);
+ TRACE_AND_STEP();
+ M.x86.R_IP = destval;
+ M.x86.R_CS = destval2;
+ break;
+ case 6: /* push word ptr ... */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+
+ destval = fetch_data_long(destoffset);
+ TRACE_AND_STEP();
+ push_long(destval);
+ } else {
+ u16 destval;
+
+ destval = fetch_data_word(destoffset);
+ TRACE_AND_STEP();
+ push_word(destval);
+ }
+ break;
+ }
+ break;
+ case 3:
+ switch (rh) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = inc_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = inc_word(*destreg);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = dec_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = dec_word(*destreg);
+ }
+ break;
+ case 2: /* call word ptr ... */
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = *destreg;
+ break;
+ case 3: /* jmp far ptr ... */
+ DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
+ TRACE_AND_STEP();
+ HALT_SYS();
+ break;
+
+ case 4: /* jmp ... */
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ M.x86.R_IP = (u16) (*destreg);
+ break;
+ case 5: /* jmp far ptr ... */
+ DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
+ TRACE_AND_STEP();
+ HALT_SYS();
+ break;
+ case 6:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ push_long(*destreg);
+ } else {
+ u16 *destreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ push_word(*destreg);
+ }
+ break;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/***************************************************************************
+ * Single byte operation code table:
+ **************************************************************************/
+void (*x86emu_optab[256])(u8) =
+{
+/* 0x00 */ x86emuOp_add_byte_RM_R,
+/* 0x01 */ x86emuOp_add_word_RM_R,
+/* 0x02 */ x86emuOp_add_byte_R_RM,
+/* 0x03 */ x86emuOp_add_word_R_RM,
+/* 0x04 */ x86emuOp_add_byte_AL_IMM,
+/* 0x05 */ x86emuOp_add_word_AX_IMM,
+/* 0x06 */ x86emuOp_push_ES,
+/* 0x07 */ x86emuOp_pop_ES,
+
+/* 0x08 */ x86emuOp_or_byte_RM_R,
+/* 0x09 */ x86emuOp_or_word_RM_R,
+/* 0x0a */ x86emuOp_or_byte_R_RM,
+/* 0x0b */ x86emuOp_or_word_R_RM,
+/* 0x0c */ x86emuOp_or_byte_AL_IMM,
+/* 0x0d */ x86emuOp_or_word_AX_IMM,
+/* 0x0e */ x86emuOp_push_CS,
+/* 0x0f */ x86emuOp_two_byte,
+
+/* 0x10 */ x86emuOp_adc_byte_RM_R,
+/* 0x11 */ x86emuOp_adc_word_RM_R,
+/* 0x12 */ x86emuOp_adc_byte_R_RM,
+/* 0x13 */ x86emuOp_adc_word_R_RM,
+/* 0x14 */ x86emuOp_adc_byte_AL_IMM,
+/* 0x15 */ x86emuOp_adc_word_AX_IMM,
+/* 0x16 */ x86emuOp_push_SS,
+/* 0x17 */ x86emuOp_pop_SS,
+
+/* 0x18 */ x86emuOp_sbb_byte_RM_R,
+/* 0x19 */ x86emuOp_sbb_word_RM_R,
+/* 0x1a */ x86emuOp_sbb_byte_R_RM,
+/* 0x1b */ x86emuOp_sbb_word_R_RM,
+/* 0x1c */ x86emuOp_sbb_byte_AL_IMM,
+/* 0x1d */ x86emuOp_sbb_word_AX_IMM,
+/* 0x1e */ x86emuOp_push_DS,
+/* 0x1f */ x86emuOp_pop_DS,
+
+/* 0x20 */ x86emuOp_and_byte_RM_R,
+/* 0x21 */ x86emuOp_and_word_RM_R,
+/* 0x22 */ x86emuOp_and_byte_R_RM,
+/* 0x23 */ x86emuOp_and_word_R_RM,
+/* 0x24 */ x86emuOp_and_byte_AL_IMM,
+/* 0x25 */ x86emuOp_and_word_AX_IMM,
+/* 0x26 */ x86emuOp_segovr_ES,
+/* 0x27 */ x86emuOp_daa,
+
+/* 0x28 */ x86emuOp_sub_byte_RM_R,
+/* 0x29 */ x86emuOp_sub_word_RM_R,
+/* 0x2a */ x86emuOp_sub_byte_R_RM,
+/* 0x2b */ x86emuOp_sub_word_R_RM,
+/* 0x2c */ x86emuOp_sub_byte_AL_IMM,
+/* 0x2d */ x86emuOp_sub_word_AX_IMM,
+/* 0x2e */ x86emuOp_segovr_CS,
+/* 0x2f */ x86emuOp_das,
+
+/* 0x30 */ x86emuOp_xor_byte_RM_R,
+/* 0x31 */ x86emuOp_xor_word_RM_R,
+/* 0x32 */ x86emuOp_xor_byte_R_RM,
+/* 0x33 */ x86emuOp_xor_word_R_RM,
+/* 0x34 */ x86emuOp_xor_byte_AL_IMM,
+/* 0x35 */ x86emuOp_xor_word_AX_IMM,
+/* 0x36 */ x86emuOp_segovr_SS,
+/* 0x37 */ x86emuOp_aaa,
+
+/* 0x38 */ x86emuOp_cmp_byte_RM_R,
+/* 0x39 */ x86emuOp_cmp_word_RM_R,
+/* 0x3a */ x86emuOp_cmp_byte_R_RM,
+/* 0x3b */ x86emuOp_cmp_word_R_RM,
+/* 0x3c */ x86emuOp_cmp_byte_AL_IMM,
+/* 0x3d */ x86emuOp_cmp_word_AX_IMM,
+/* 0x3e */ x86emuOp_segovr_DS,
+/* 0x3f */ x86emuOp_aas,
+
+/* 0x40 */ x86emuOp_inc_AX,
+/* 0x41 */ x86emuOp_inc_CX,
+/* 0x42 */ x86emuOp_inc_DX,
+/* 0x43 */ x86emuOp_inc_BX,
+/* 0x44 */ x86emuOp_inc_SP,
+/* 0x45 */ x86emuOp_inc_BP,
+/* 0x46 */ x86emuOp_inc_SI,
+/* 0x47 */ x86emuOp_inc_DI,
+
+/* 0x48 */ x86emuOp_dec_AX,
+/* 0x49 */ x86emuOp_dec_CX,
+/* 0x4a */ x86emuOp_dec_DX,
+/* 0x4b */ x86emuOp_dec_BX,
+/* 0x4c */ x86emuOp_dec_SP,
+/* 0x4d */ x86emuOp_dec_BP,
+/* 0x4e */ x86emuOp_dec_SI,
+/* 0x4f */ x86emuOp_dec_DI,
+
+/* 0x50 */ x86emuOp_push_AX,
+/* 0x51 */ x86emuOp_push_CX,
+/* 0x52 */ x86emuOp_push_DX,
+/* 0x53 */ x86emuOp_push_BX,
+/* 0x54 */ x86emuOp_push_SP,
+/* 0x55 */ x86emuOp_push_BP,
+/* 0x56 */ x86emuOp_push_SI,
+/* 0x57 */ x86emuOp_push_DI,
+
+/* 0x58 */ x86emuOp_pop_AX,
+/* 0x59 */ x86emuOp_pop_CX,
+/* 0x5a */ x86emuOp_pop_DX,
+/* 0x5b */ x86emuOp_pop_BX,
+/* 0x5c */ x86emuOp_pop_SP,
+/* 0x5d */ x86emuOp_pop_BP,
+/* 0x5e */ x86emuOp_pop_SI,
+/* 0x5f */ x86emuOp_pop_DI,
+
+/* 0x60 */ x86emuOp_push_all,
+/* 0x61 */ x86emuOp_pop_all,
+/* 0x62 */ x86emuOp_illegal_op, /* bound */
+/* 0x63 */ x86emuOp_illegal_op, /* arpl */
+/* 0x64 */ x86emuOp_segovr_FS,
+/* 0x65 */ x86emuOp_segovr_GS,
+/* 0x66 */ x86emuOp_prefix_data,
+/* 0x67 */ x86emuOp_prefix_addr,
+
+/* 0x68 */ x86emuOp_push_word_IMM,
+/* 0x69 */ x86emuOp_imul_word_IMM,
+/* 0x6a */ x86emuOp_push_byte_IMM,
+/* 0x6b */ x86emuOp_imul_byte_IMM,
+/* 0x6c */ x86emuOp_ins_byte,
+/* 0x6d */ x86emuOp_ins_word,
+/* 0x6e */ x86emuOp_outs_byte,
+/* 0x6f */ x86emuOp_outs_word,
+
+/* 0x70 */ x86emuOp_jump_near_O,
+/* 0x71 */ x86emuOp_jump_near_NO,
+/* 0x72 */ x86emuOp_jump_near_B,
+/* 0x73 */ x86emuOp_jump_near_NB,
+/* 0x74 */ x86emuOp_jump_near_Z,
+/* 0x75 */ x86emuOp_jump_near_NZ,
+/* 0x76 */ x86emuOp_jump_near_BE,
+/* 0x77 */ x86emuOp_jump_near_NBE,
+
+/* 0x78 */ x86emuOp_jump_near_S,
+/* 0x79 */ x86emuOp_jump_near_NS,
+/* 0x7a */ x86emuOp_jump_near_P,
+/* 0x7b */ x86emuOp_jump_near_NP,
+/* 0x7c */ x86emuOp_jump_near_L,
+/* 0x7d */ x86emuOp_jump_near_NL,
+/* 0x7e */ x86emuOp_jump_near_LE,
+/* 0x7f */ x86emuOp_jump_near_NLE,
+
+/* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
+/* 0x81 */ x86emuOp_opc81_word_RM_IMM,
+/* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
+/* 0x83 */ x86emuOp_opc83_word_RM_IMM,
+/* 0x84 */ x86emuOp_test_byte_RM_R,
+/* 0x85 */ x86emuOp_test_word_RM_R,
+/* 0x86 */ x86emuOp_xchg_byte_RM_R,
+/* 0x87 */ x86emuOp_xchg_word_RM_R,
+
+/* 0x88 */ x86emuOp_mov_byte_RM_R,
+/* 0x89 */ x86emuOp_mov_word_RM_R,
+/* 0x8a */ x86emuOp_mov_byte_R_RM,
+/* 0x8b */ x86emuOp_mov_word_R_RM,
+/* 0x8c */ x86emuOp_mov_word_RM_SR,
+/* 0x8d */ x86emuOp_lea_word_R_M,
+/* 0x8e */ x86emuOp_mov_word_SR_RM,
+/* 0x8f */ x86emuOp_pop_RM,
+
+/* 0x90 */ x86emuOp_nop,
+/* 0x91 */ x86emuOp_xchg_word_AX_CX,
+/* 0x92 */ x86emuOp_xchg_word_AX_DX,
+/* 0x93 */ x86emuOp_xchg_word_AX_BX,
+/* 0x94 */ x86emuOp_xchg_word_AX_SP,
+/* 0x95 */ x86emuOp_xchg_word_AX_BP,
+/* 0x96 */ x86emuOp_xchg_word_AX_SI,
+/* 0x97 */ x86emuOp_xchg_word_AX_DI,
+
+/* 0x98 */ x86emuOp_cbw,
+/* 0x99 */ x86emuOp_cwd,
+/* 0x9a */ x86emuOp_call_far_IMM,
+/* 0x9b */ x86emuOp_wait,
+/* 0x9c */ x86emuOp_pushf_word,
+/* 0x9d */ x86emuOp_popf_word,
+/* 0x9e */ x86emuOp_sahf,
+/* 0x9f */ x86emuOp_lahf,
+
+/* 0xa0 */ x86emuOp_mov_AL_M_IMM,
+/* 0xa1 */ x86emuOp_mov_AX_M_IMM,
+/* 0xa2 */ x86emuOp_mov_M_AL_IMM,
+/* 0xa3 */ x86emuOp_mov_M_AX_IMM,
+/* 0xa4 */ x86emuOp_movs_byte,
+/* 0xa5 */ x86emuOp_movs_word,
+/* 0xa6 */ x86emuOp_cmps_byte,
+/* 0xa7 */ x86emuOp_cmps_word,
+/* 0xa8 */ x86emuOp_test_AL_IMM,
+/* 0xa9 */ x86emuOp_test_AX_IMM,
+/* 0xaa */ x86emuOp_stos_byte,
+/* 0xab */ x86emuOp_stos_word,
+/* 0xac */ x86emuOp_lods_byte,
+/* 0xad */ x86emuOp_lods_word,
+/* 0xac */ x86emuOp_scas_byte,
+/* 0xad */ x86emuOp_scas_word,
+
+
+/* 0xb0 */ x86emuOp_mov_byte_AL_IMM,
+/* 0xb1 */ x86emuOp_mov_byte_CL_IMM,
+/* 0xb2 */ x86emuOp_mov_byte_DL_IMM,
+/* 0xb3 */ x86emuOp_mov_byte_BL_IMM,
+/* 0xb4 */ x86emuOp_mov_byte_AH_IMM,
+/* 0xb5 */ x86emuOp_mov_byte_CH_IMM,
+/* 0xb6 */ x86emuOp_mov_byte_DH_IMM,
+/* 0xb7 */ x86emuOp_mov_byte_BH_IMM,
+
+/* 0xb8 */ x86emuOp_mov_word_AX_IMM,
+/* 0xb9 */ x86emuOp_mov_word_CX_IMM,
+/* 0xba */ x86emuOp_mov_word_DX_IMM,
+/* 0xbb */ x86emuOp_mov_word_BX_IMM,
+/* 0xbc */ x86emuOp_mov_word_SP_IMM,
+/* 0xbd */ x86emuOp_mov_word_BP_IMM,
+/* 0xbe */ x86emuOp_mov_word_SI_IMM,
+/* 0xbf */ x86emuOp_mov_word_DI_IMM,
+
+/* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
+/* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
+/* 0xc2 */ x86emuOp_ret_near_IMM,
+/* 0xc3 */ x86emuOp_ret_near,
+/* 0xc4 */ x86emuOp_les_R_IMM,
+/* 0xc5 */ x86emuOp_lds_R_IMM,
+/* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
+/* 0xc7 */ x86emuOp_mov_word_RM_IMM,
+/* 0xc8 */ x86emuOp_enter,
+/* 0xc9 */ x86emuOp_leave,
+/* 0xca */ x86emuOp_ret_far_IMM,
+/* 0xcb */ x86emuOp_ret_far,
+/* 0xcc */ x86emuOp_int3,
+/* 0xcd */ x86emuOp_int_IMM,
+/* 0xce */ x86emuOp_into,
+/* 0xcf */ x86emuOp_iret,
+
+/* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
+/* 0xd1 */ x86emuOp_opcD1_word_RM_1,
+/* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
+/* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
+/* 0xd4 */ x86emuOp_aam,
+/* 0xd5 */ x86emuOp_aad,
+/* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
+/* 0xd7 */ x86emuOp_xlat,
+/* 0xd8 */ x86emuOp_esc_coprocess_d8,
+/* 0xd9 */ x86emuOp_esc_coprocess_d9,
+/* 0xda */ x86emuOp_esc_coprocess_da,
+/* 0xdb */ x86emuOp_esc_coprocess_db,
+/* 0xdc */ x86emuOp_esc_coprocess_dc,
+/* 0xdd */ x86emuOp_esc_coprocess_dd,
+/* 0xde */ x86emuOp_esc_coprocess_de,
+/* 0xdf */ x86emuOp_esc_coprocess_df,
+
+/* 0xe0 */ x86emuOp_loopne,
+/* 0xe1 */ x86emuOp_loope,
+/* 0xe2 */ x86emuOp_loop,
+/* 0xe3 */ x86emuOp_jcxz,
+/* 0xe4 */ x86emuOp_in_byte_AL_IMM,
+/* 0xe5 */ x86emuOp_in_word_AX_IMM,
+/* 0xe6 */ x86emuOp_out_byte_IMM_AL,
+/* 0xe7 */ x86emuOp_out_word_IMM_AX,
+
+/* 0xe8 */ x86emuOp_call_near_IMM,
+/* 0xe9 */ x86emuOp_jump_near_IMM,
+/* 0xea */ x86emuOp_jump_far_IMM,
+/* 0xeb */ x86emuOp_jump_byte_IMM,
+/* 0xec */ x86emuOp_in_byte_AL_DX,
+/* 0xed */ x86emuOp_in_word_AX_DX,
+/* 0xee */ x86emuOp_out_byte_DX_AL,
+/* 0xef */ x86emuOp_out_word_DX_AX,
+
+/* 0xf0 */ x86emuOp_lock,
+/* 0xf1 */ x86emuOp_illegal_op,
+/* 0xf2 */ x86emuOp_repne,
+/* 0xf3 */ x86emuOp_repe,
+/* 0xf4 */ x86emuOp_halt,
+/* 0xf5 */ x86emuOp_cmc,
+/* 0xf6 */ x86emuOp_opcF6_byte_RM,
+/* 0xf7 */ x86emuOp_opcF7_word_RM,
+
+/* 0xf8 */ x86emuOp_clc,
+/* 0xf9 */ x86emuOp_stc,
+/* 0xfa */ x86emuOp_cli,
+/* 0xfb */ x86emuOp_sti,
+/* 0xfc */ x86emuOp_cld,
+/* 0xfd */ x86emuOp_std,
+/* 0xfe */ x86emuOp_opcFE_byte_RM,
+/* 0xff */ x86emuOp_opcFF_word_RM,
+};
diff --git a/cfe/cfe/x86emu/ops2.c b/cfe/cfe/x86emu/ops2.c
new file mode 100644
index 0000000..c59c813
--- /dev/null
+++ b/cfe/cfe/x86emu/ops2.c
@@ -0,0 +1,2802 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: This file includes subroutines to implement the decoding
+* and emulation of all the x86 extended two-byte processor
+* instructions.
+*
+****************************************************************************/
+/* $XFree86: xc/extras/x86emu/src/x86emu/ops2.c,v 1.4 2000/11/16 19:44:50 eich Exp $ */
+
+#include "x86emu/x86emui.h"
+#include "x86emu/ops_protos.h"
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+PARAMETERS:
+op1 - Instruction op code
+
+REMARKS:
+Handles illegal opcodes.
+****************************************************************************/
+void x86emuOp2_illegal_op(
+ u8 op2)
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
+ TRACE_REGS();
+ printk("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n",
+ M.x86.R_CS, M.x86.R_IP-2,op2);
+ HALT_SYS();
+ END_OF_INSTR();
+}
+
+#define xorl(a,b) ((a) && !(b)) || (!(a) && (b))
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0x80-0x8F
+****************************************************************************/
+void x86emuOp2_long_jump(u8 op2)
+{
+ s32 target;
+ char *name = 0;
+ int cond = 0;
+
+ /* conditional jump to word offset. */
+ START_OF_INSTR();
+ switch (op2) {
+ case 0x80:
+ name = "JO\t";
+ cond = ACCESS_FLAG(F_OF);
+ break;
+ case 0x81:
+ name = "JNO\t";
+ cond = !ACCESS_FLAG(F_OF);
+ break;
+ case 0x82:
+ name = "JB\t";
+ cond = ACCESS_FLAG(F_CF);
+ break;
+ case 0x83:
+ name = "JNB\t";
+ cond = !ACCESS_FLAG(F_CF);
+ break;
+ case 0x84:
+ name = "JZ\t";
+ cond = ACCESS_FLAG(F_ZF);
+ break;
+ case 0x85:
+ name = "JNZ\t";
+ cond = !ACCESS_FLAG(F_ZF);
+ break;
+ case 0x86:
+ name = "JBE\t";
+ cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
+ break;
+ case 0x87:
+ name = "JNBE\t";
+ cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
+ break;
+ case 0x88:
+ name = "JS\t";
+ cond = ACCESS_FLAG(F_SF);
+ break;
+ case 0x89:
+ name = "JNS\t";
+ cond = !ACCESS_FLAG(F_SF);
+ break;
+ case 0x8a:
+ name = "JP\t";
+ cond = ACCESS_FLAG(F_PF);
+ break;
+ case 0x8b:
+ name = "JNP\t";
+ cond = !ACCESS_FLAG(F_PF);
+ break;
+ case 0x8c:
+ name = "JL\t";
+ cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
+ break;
+ case 0x8d:
+ name = "JNL\t";
+ cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
+ break;
+ case 0x8e:
+ name = "JLE\t";
+ cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
+ ACCESS_FLAG(F_ZF));
+ break;
+ case 0x8f:
+ name = "JNLE\t";
+ cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
+ ACCESS_FLAG(F_ZF));
+ break;
+ }
+ DECODE_PRINTF(name);
+ target = (s16) fetch_word_imm();
+ target += (s16) M.x86.R_IP;
+ DECODE_PRINTF2("%04x\n", target);
+ TRACE_AND_STEP();
+ if (cond)
+ M.x86.R_IP = (u16)target;
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0x90-0x9F
+****************************************************************************/
+void x86emuOp2_set_byte(u8 op2)
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 *destreg;
+ char *name = 0;
+ int cond = 0;
+
+ START_OF_INSTR();
+ switch (op2) {
+ case 0x90:
+ name = "SETO\t";
+ cond = ACCESS_FLAG(F_OF);
+ break;
+ case 0x91:
+ name = "SETNO\t";
+ cond = !ACCESS_FLAG(F_OF);
+ break;
+ case 0x92:
+ name = "SETB\t";
+ cond = ACCESS_FLAG(F_CF);
+ break;
+ case 0x93:
+ name = "SETNB\t";
+ cond = !ACCESS_FLAG(F_CF);
+ break;
+ case 0x94:
+ name = "SETZ\t";
+ cond = ACCESS_FLAG(F_ZF);
+ break;
+ case 0x95:
+ name = "SETNZ\t";
+ cond = !ACCESS_FLAG(F_ZF);
+ break;
+ case 0x96:
+ name = "SETBE\t";
+ cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF);
+ break;
+ case 0x97:
+ name = "SETNBE\t";
+ cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
+ break;
+ case 0x98:
+ name = "SETS\t";
+ cond = ACCESS_FLAG(F_SF);
+ break;
+ case 0x99:
+ name = "SETNS\t";
+ cond = !ACCESS_FLAG(F_SF);
+ break;
+ case 0x9a:
+ name = "SETP\t";
+ cond = ACCESS_FLAG(F_PF);
+ break;
+ case 0x9b:
+ name = "SETNP\t";
+ cond = !ACCESS_FLAG(F_PF);
+ break;
+ case 0x9c:
+ name = "SETL\t";
+ cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
+ break;
+ case 0x9d:
+ name = "SETNL\t";
+ cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF));
+ break;
+ case 0x9e:
+ name = "SETLE\t";
+ cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
+ ACCESS_FLAG(F_ZF));
+ break;
+ case 0x9f:
+ name = "SETNLE\t";
+ cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
+ ACCESS_FLAG(F_ZF));
+ break;
+ }
+ DECODE_PRINTF(name);
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destoffset = decode_rm00_address(rl);
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, cond ? 0x01 : 0x00);
+ break;
+ case 1:
+ destoffset = decode_rm01_address(rl);
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, cond ? 0x01 : 0x00);
+ break;
+ case 2:
+ destoffset = decode_rm10_address(rl);
+ TRACE_AND_STEP();
+ store_data_byte(destoffset, cond ? 0x01 : 0x00);
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_BYTE_REGISTER(rl);
+ TRACE_AND_STEP();
+ *destreg = cond ? 0x01 : 0x00;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa0
+****************************************************************************/
+void x86emuOp2_push_FS(u8 X86EMU_UNUSED(op2))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("PUSH\tFS\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_FS);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa1
+****************************************************************************/
+void x86emuOp2_pop_FS(u8 X86EMU_UNUSED(op2))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("POP\tFS\n");
+ TRACE_AND_STEP();
+ M.x86.R_FS = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa3
+****************************************************************************/
+void x86emuOp2_bt_R(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ int bit,disp;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("BT\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval;
+ u32 *shiftreg;
+
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ disp = (s16)*shiftreg >> 5;
+ srcval = fetch_data_long(srcoffset+disp);
+ CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
+ } else {
+ u16 srcval;
+ u16 *shiftreg;
+
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ disp = (s16)*shiftreg >> 4;
+ srcval = fetch_data_word(srcoffset+disp);
+ CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval;
+ u32 *shiftreg;
+
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ disp = (s16)*shiftreg >> 5;
+ srcval = fetch_data_long(srcoffset+disp);
+ CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
+ } else {
+ u16 srcval;
+ u16 *shiftreg;
+
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ disp = (s16)*shiftreg >> 4;
+ srcval = fetch_data_word(srcoffset+disp);
+ CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval;
+ u32 *shiftreg;
+
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ disp = (s16)*shiftreg >> 5;
+ srcval = fetch_data_long(srcoffset+disp);
+ CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
+ } else {
+ u16 srcval;
+ u16 *shiftreg;
+
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ disp = (s16)*shiftreg >> 4;
+ srcval = fetch_data_word(srcoffset+disp);
+ CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg,*shiftreg;
+
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
+ } else {
+ u16 *srcreg,*shiftreg;
+
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa4
+****************************************************************************/
+void x86emuOp2_shld_IMM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 shift;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SHLD\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *shiftreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ destval = fetch_data_long(destoffset);
+ destval = shld_long(destval,*shiftreg,shift);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *shiftreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ destval = fetch_data_word(destoffset);
+ destval = shld_word(destval,*shiftreg,shift);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *shiftreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ destval = fetch_data_long(destoffset);
+ destval = shld_long(destval,*shiftreg,shift);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *shiftreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ destval = fetch_data_word(destoffset);
+ destval = shld_word(destval,*shiftreg,shift);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *shiftreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ destval = fetch_data_long(destoffset);
+ destval = shld_long(destval,*shiftreg,shift);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *shiftreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ destval = fetch_data_word(destoffset);
+ destval = shld_word(destval,*shiftreg,shift);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*shiftreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ *destreg = shld_long(*destreg,*shiftreg,shift);
+ } else {
+ u16 *destreg,*shiftreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ *destreg = shld_word(*destreg,*shiftreg,shift);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa5
+****************************************************************************/
+void x86emuOp2_shld_CL(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SHLD\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *shiftreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = fetch_data_long(destoffset);
+ destval = shld_long(destval,*shiftreg,M.x86.R_CL);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *shiftreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = fetch_data_word(destoffset);
+ destval = shld_word(destval,*shiftreg,M.x86.R_CL);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *shiftreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = fetch_data_long(destoffset);
+ destval = shld_long(destval,*shiftreg,M.x86.R_CL);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *shiftreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = fetch_data_word(destoffset);
+ destval = shld_word(destval,*shiftreg,M.x86.R_CL);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *shiftreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = fetch_data_long(destoffset);
+ destval = shld_long(destval,*shiftreg,M.x86.R_CL);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *shiftreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = fetch_data_word(destoffset);
+ destval = shld_word(destval,*shiftreg,M.x86.R_CL);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*shiftreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ *destreg = shld_long(*destreg,*shiftreg,M.x86.R_CL);
+ } else {
+ u16 *destreg,*shiftreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ *destreg = shld_word(*destreg,*shiftreg,M.x86.R_CL);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa8
+****************************************************************************/
+void x86emuOp2_push_GS(u8 X86EMU_UNUSED(op2))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("PUSH\tGS\n");
+ TRACE_AND_STEP();
+ push_word(M.x86.R_GS);
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xa9
+****************************************************************************/
+void x86emuOp2_pop_GS(u8 X86EMU_UNUSED(op2))
+{
+ START_OF_INSTR();
+ DECODE_PRINTF("POP\tGS\n");
+ TRACE_AND_STEP();
+ M.x86.R_GS = pop_word();
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xaa
+****************************************************************************/
+void x86emuOp2_bts_R(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ int bit,disp;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("BTS\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval,mask;
+ u32 *shiftreg;
+
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ disp = (s16)*shiftreg >> 5;
+ srcval = fetch_data_long(srcoffset+disp);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_long(srcoffset+disp, srcval | mask);
+ } else {
+ u16 srcval,mask;
+ u16 *shiftreg;
+
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ disp = (s16)*shiftreg >> 4;
+ srcval = fetch_data_word(srcoffset+disp);
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_word(srcoffset+disp, srcval | mask);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval,mask;
+ u32 *shiftreg;
+
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ disp = (s16)*shiftreg >> 5;
+ srcval = fetch_data_long(srcoffset+disp);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_long(srcoffset+disp, srcval | mask);
+ } else {
+ u16 srcval,mask;
+ u16 *shiftreg;
+
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ disp = (s16)*shiftreg >> 4;
+ srcval = fetch_data_word(srcoffset+disp);
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_word(srcoffset+disp, srcval | mask);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval,mask;
+ u32 *shiftreg;
+
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ disp = (s16)*shiftreg >> 5;
+ srcval = fetch_data_long(srcoffset+disp);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_long(srcoffset+disp, srcval | mask);
+ } else {
+ u16 srcval,mask;
+ u16 *shiftreg;
+
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ disp = (s16)*shiftreg >> 4;
+ srcval = fetch_data_word(srcoffset+disp);
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_word(srcoffset+disp, srcval | mask);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg,*shiftreg;
+ u32 mask;
+
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+ *srcreg |= mask;
+ } else {
+ u16 *srcreg,*shiftreg;
+ u16 mask;
+
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+ *srcreg |= mask;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xac
+****************************************************************************/
+void x86emuOp2_shrd_IMM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint destoffset;
+ u8 shift;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SHLD\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *shiftreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ destval = fetch_data_long(destoffset);
+ destval = shrd_long(destval,*shiftreg,shift);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *shiftreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ destval = fetch_data_word(destoffset);
+ destval = shrd_word(destval,*shiftreg,shift);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *shiftreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ destval = fetch_data_long(destoffset);
+ destval = shrd_long(destval,*shiftreg,shift);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *shiftreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ destval = fetch_data_word(destoffset);
+ destval = shrd_word(destval,*shiftreg,shift);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *shiftreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ destval = fetch_data_long(destoffset);
+ destval = shrd_long(destval,*shiftreg,shift);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *shiftreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ destval = fetch_data_word(destoffset);
+ destval = shrd_word(destval,*shiftreg,shift);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*shiftreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ *destreg = shrd_long(*destreg,*shiftreg,shift);
+ } else {
+ u16 *destreg,*shiftreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ DECODE_PRINTF2("%d\n", shift);
+ TRACE_AND_STEP();
+ *destreg = shrd_word(*destreg,*shiftreg,shift);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xad
+****************************************************************************/
+void x86emuOp2_shrd_CL(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint destoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("SHLD\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *shiftreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = fetch_data_long(destoffset);
+ destval = shrd_long(destval,*shiftreg,M.x86.R_CL);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *shiftreg;
+
+ destoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = fetch_data_word(destoffset);
+ destval = shrd_word(destval,*shiftreg,M.x86.R_CL);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *shiftreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = fetch_data_long(destoffset);
+ destval = shrd_long(destval,*shiftreg,M.x86.R_CL);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *shiftreg;
+
+ destoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = fetch_data_word(destoffset);
+ destval = shrd_word(destval,*shiftreg,M.x86.R_CL);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 destval;
+ u32 *shiftreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = fetch_data_long(destoffset);
+ destval = shrd_long(destval,*shiftreg,M.x86.R_CL);
+ store_data_long(destoffset, destval);
+ } else {
+ u16 destval;
+ u16 *shiftreg;
+
+ destoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ destval = fetch_data_word(destoffset);
+ destval = shrd_word(destval,*shiftreg,M.x86.R_CL);
+ store_data_word(destoffset, destval);
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*shiftreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ *destreg = shrd_long(*destreg,*shiftreg,M.x86.R_CL);
+ } else {
+ u16 *destreg,*shiftreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",CL\n");
+ TRACE_AND_STEP();
+ *destreg = shrd_word(*destreg,*shiftreg,M.x86.R_CL);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xaf
+****************************************************************************/
+void x86emuOp2_imul_R_RM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("IMUL\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ TRACE_AND_STEP();
+ res = (s16)*destreg * (s16)srcval;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ TRACE_AND_STEP();
+ res = (s16)*destreg * (s16)srcval;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+ u32 res_lo,res_hi;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_long(srcoffset);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+ u32 res;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ TRACE_AND_STEP();
+ res = (s16)*destreg * (s16)srcval;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg,*srcreg;
+ u32 res_lo,res_hi;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ TRACE_AND_STEP();
+ imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)*srcreg);
+ if (res_hi != 0) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u32)res_lo;
+ } else {
+ u16 *destreg,*srcreg;
+ u32 res;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ res = (s16)*destreg * (s16)*srcreg;
+ if (res > 0xFFFF) {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ }
+ *destreg = (u16)res;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb2
+****************************************************************************/
+void x86emuOp2_lss_R_IMM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rh, rl;
+ u16 *dstreg;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LSS\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_SS = fetch_data_word(srcoffset + 2);
+ break;
+ case 1:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_SS = fetch_data_word(srcoffset + 2);
+ break;
+ case 2:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_SS = fetch_data_word(srcoffset + 2);
+ break;
+ case 3: /* register to register */
+ /* UNDEFINED! */
+ TRACE_AND_STEP();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb3
+****************************************************************************/
+void x86emuOp2_btr_R(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ int bit,disp;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("BTR\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval,mask;
+ u32 *shiftreg;
+
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ disp = (s16)*shiftreg >> 5;
+ srcval = fetch_data_long(srcoffset+disp);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_long(srcoffset+disp, srcval & ~mask);
+ } else {
+ u16 srcval,mask;
+ u16 *shiftreg;
+
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ disp = (s16)*shiftreg >> 4;
+ srcval = fetch_data_word(srcoffset+disp);
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_word(srcoffset+disp, (u16)(srcval & ~mask));
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval,mask;
+ u32 *shiftreg;
+
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ disp = (s16)*shiftreg >> 5;
+ srcval = fetch_data_long(srcoffset+disp);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_long(srcoffset+disp, srcval & ~mask);
+ } else {
+ u16 srcval,mask;
+ u16 *shiftreg;
+
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ disp = (s16)*shiftreg >> 4;
+ srcval = fetch_data_word(srcoffset+disp);
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_word(srcoffset+disp, (u16)(srcval & ~mask));
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval,mask;
+ u32 *shiftreg;
+
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ disp = (s16)*shiftreg >> 5;
+ srcval = fetch_data_long(srcoffset+disp);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_long(srcoffset+disp, srcval & ~mask);
+ } else {
+ u16 srcval,mask;
+ u16 *shiftreg;
+
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ disp = (s16)*shiftreg >> 4;
+ srcval = fetch_data_word(srcoffset+disp);
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_word(srcoffset+disp, (u16)(srcval & ~mask));
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg,*shiftreg;
+ u32 mask;
+
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+ *srcreg &= ~mask;
+ } else {
+ u16 *srcreg,*shiftreg;
+ u16 mask;
+
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+ *srcreg &= ~mask;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb4
+****************************************************************************/
+void x86emuOp2_lfs_R_IMM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rh, rl;
+ u16 *dstreg;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LFS\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_FS = fetch_data_word(srcoffset + 2);
+ break;
+ case 1:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_FS = fetch_data_word(srcoffset + 2);
+ break;
+ case 2:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_FS = fetch_data_word(srcoffset + 2);
+ break;
+ case 3: /* register to register */
+ /* UNDEFINED! */
+ TRACE_AND_STEP();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb5
+****************************************************************************/
+void x86emuOp2_lgs_R_IMM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rh, rl;
+ u16 *dstreg;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("LGS\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_GS = fetch_data_word(srcoffset + 2);
+ break;
+ case 1:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_GS = fetch_data_word(srcoffset + 2);
+ break;
+ case 2:
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *dstreg = fetch_data_word(srcoffset);
+ M.x86.R_GS = fetch_data_word(srcoffset + 2);
+ break;
+ case 3: /* register to register */
+ /* UNDEFINED! */
+ TRACE_AND_STEP();
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb6
+****************************************************************************/
+void x86emuOp2_movzx_byte_R_RM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOVZX\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_byte(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u8 *srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ } else {
+ u16 *destreg;
+ u8 *srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xb7
+****************************************************************************/
+void x86emuOp2_movzx_word_R_RM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ u32 *destreg;
+ u32 srcval;
+ u16 *srcreg;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOVZX\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 1:
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 2:
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = fetch_data_word(srcoffset);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = *srcreg;
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xba
+****************************************************************************/
+void x86emuOp2_btX_I(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ int bit;
+
+ START_OF_INSTR();
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (rh) {
+ case 3:
+ DECODE_PRINTF("BT\t");
+ break;
+ case 4:
+ DECODE_PRINTF("BTS\t");
+ break;
+ case 5:
+ DECODE_PRINTF("BTR\t");
+ break;
+ case 6:
+ DECODE_PRINTF("BTC\t");
+ break;
+ default:
+ DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
+ TRACE_REGS();
+ printk("%04x:%04x: %02X%02X ILLEGAL EXTENDED X86 OPCODE EXTENSION!\n",
+ M.x86.R_CS, M.x86.R_IP-3,op2, (mod<<6)|(rh<<3)|rl);
+ HALT_SYS();
+ }
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval, mask;
+ u8 shift;
+
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ TRACE_AND_STEP();
+ bit = shift & 0x1F;
+ srcval = fetch_data_long(srcoffset);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ switch (rh) {
+ case 4:
+ store_data_long(srcoffset, srcval | mask);
+ break;
+ case 5:
+ store_data_long(srcoffset, srcval & ~mask);
+ break;
+ case 6:
+ store_data_long(srcoffset, srcval ^ mask);
+ break;
+ default:
+ break;
+ }
+ } else {
+ u16 srcval, mask;
+ u8 shift;
+
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ TRACE_AND_STEP();
+ bit = shift & 0xF;
+ srcval = fetch_data_word(srcoffset);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ switch (rh) {
+ case 4:
+ store_data_word(srcoffset, srcval | mask);
+ break;
+ case 5:
+ store_data_word(srcoffset, srcval & ~mask);
+ break;
+ case 6:
+ store_data_word(srcoffset, srcval ^ mask);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval, mask;
+ u8 shift;
+
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ TRACE_AND_STEP();
+ bit = shift & 0x1F;
+ srcval = fetch_data_long(srcoffset);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ switch (rh) {
+ case 4:
+ store_data_long(srcoffset, srcval | mask);
+ break;
+ case 5:
+ store_data_long(srcoffset, srcval & ~mask);
+ break;
+ case 6:
+ store_data_long(srcoffset, srcval ^ mask);
+ break;
+ default:
+ break;
+ }
+ } else {
+ u16 srcval, mask;
+ u8 shift;
+
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ TRACE_AND_STEP();
+ bit = shift & 0xF;
+ srcval = fetch_data_word(srcoffset);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ switch (rh) {
+ case 4:
+ store_data_word(srcoffset, srcval | mask);
+ break;
+ case 5:
+ store_data_word(srcoffset, srcval & ~mask);
+ break;
+ case 6:
+ store_data_word(srcoffset, srcval ^ mask);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval, mask;
+ u8 shift;
+
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ TRACE_AND_STEP();
+ bit = shift & 0x1F;
+ srcval = fetch_data_long(srcoffset);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ switch (rh) {
+ case 4:
+ store_data_long(srcoffset, srcval | mask);
+ break;
+ case 5:
+ store_data_long(srcoffset, srcval & ~mask);
+ break;
+ case 6:
+ store_data_long(srcoffset, srcval ^ mask);
+ break;
+ default:
+ break;
+ }
+ } else {
+ u16 srcval, mask;
+ u8 shift;
+
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ TRACE_AND_STEP();
+ bit = shift & 0xF;
+ srcval = fetch_data_word(srcoffset);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ switch (rh) {
+ case 4:
+ store_data_word(srcoffset, srcval | mask);
+ break;
+ case 5:
+ store_data_word(srcoffset, srcval & ~mask);
+ break;
+ case 6:
+ store_data_word(srcoffset, srcval ^ mask);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg;
+ u32 mask;
+ u8 shift;
+
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ TRACE_AND_STEP();
+ bit = shift & 0x1F;
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+ switch (rh) {
+ case 4:
+ *srcreg |= mask;
+ break;
+ case 5:
+ *srcreg &= ~mask;
+ break;
+ case 6:
+ *srcreg ^= mask;
+ break;
+ default:
+ break;
+ }
+ } else {
+ u16 *srcreg;
+ u16 mask;
+ u8 shift;
+
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shift = fetch_byte_imm();
+ TRACE_AND_STEP();
+ bit = shift & 0xF;
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+ switch (rh) {
+ case 4:
+ *srcreg |= mask;
+ break;
+ case 5:
+ *srcreg &= ~mask;
+ break;
+ case 6:
+ *srcreg ^= mask;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbb
+****************************************************************************/
+void x86emuOp2_btc_R(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ int bit,disp;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("BTC\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval,mask;
+ u32 *shiftreg;
+
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ disp = (s16)*shiftreg >> 5;
+ srcval = fetch_data_long(srcoffset+disp);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_long(srcoffset+disp, srcval ^ mask);
+ } else {
+ u16 srcval,mask;
+ u16 *shiftreg;
+
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ disp = (s16)*shiftreg >> 4;
+ srcval = fetch_data_word(srcoffset+disp);
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_word(srcoffset+disp, (u16)(srcval ^ mask));
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval,mask;
+ u32 *shiftreg;
+
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ disp = (s16)*shiftreg >> 5;
+ srcval = fetch_data_long(srcoffset+disp);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_long(srcoffset+disp, srcval ^ mask);
+ } else {
+ u16 srcval,mask;
+ u16 *shiftreg;
+
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ disp = (s16)*shiftreg >> 4;
+ srcval = fetch_data_word(srcoffset+disp);
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_word(srcoffset+disp, (u16)(srcval ^ mask));
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval,mask;
+ u32 *shiftreg;
+
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ disp = (s16)*shiftreg >> 5;
+ srcval = fetch_data_long(srcoffset+disp);
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_long(srcoffset+disp, srcval ^ mask);
+ } else {
+ u16 srcval,mask;
+ u16 *shiftreg;
+
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ disp = (s16)*shiftreg >> 4;
+ srcval = fetch_data_word(srcoffset+disp);
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(srcval & mask,F_CF);
+ store_data_word(srcoffset+disp, (u16)(srcval ^ mask));
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg,*shiftreg;
+ u32 mask;
+
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0x1F;
+ mask = (0x1 << bit);
+ CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+ *srcreg ^= mask;
+ } else {
+ u16 *srcreg,*shiftreg;
+ u16 mask;
+
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ shiftreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ bit = *shiftreg & 0xF;
+ mask = (u16)(0x1 << bit);
+ CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF);
+ *srcreg ^= mask;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbc
+****************************************************************************/
+void x86emuOp2_bsf(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("BSF\n");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch(mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval, *dstreg;
+
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ srcval = fetch_data_long(srcoffset);
+ CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+ for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
+ if ((srcval >> *dstreg) & 1) break;
+ } else {
+ u16 srcval, *dstreg;
+
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ srcval = fetch_data_word(srcoffset);
+ CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+ for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
+ if ((srcval >> *dstreg) & 1) break;
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval, *dstreg;
+
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ srcval = fetch_data_long(srcoffset);
+ CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+ for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
+ if ((srcval >> *dstreg) & 1) break;
+ } else {
+ u16 srcval, *dstreg;
+
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ srcval = fetch_data_word(srcoffset);
+ CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+ for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
+ if ((srcval >> *dstreg) & 1) break;
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval, *dstreg;
+
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ srcval = fetch_data_long(srcoffset);
+ CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+ for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
+ if ((srcval >> *dstreg) & 1) break;
+ } else {
+ u16 srcval, *dstreg;
+
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ srcval = fetch_data_word(srcoffset);
+ CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+ for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
+ if ((srcval >> *dstreg) & 1) break;
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg, *dstreg;
+
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
+ for(*dstreg = 0; *dstreg < 32; (*dstreg)++)
+ if ((*srcreg >> *dstreg) & 1) break;
+ } else {
+ u16 *srcreg, *dstreg;
+
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
+ for(*dstreg = 0; *dstreg < 16; (*dstreg)++)
+ if ((*srcreg >> *dstreg) & 1) break;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbd
+****************************************************************************/
+void x86emuOp2_bsr(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("BSF\n");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch(mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval, *dstreg;
+
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ srcval = fetch_data_long(srcoffset);
+ CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+ for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
+ if ((srcval >> *dstreg) & 1) break;
+ } else {
+ u16 srcval, *dstreg;
+
+ srcoffset = decode_rm00_address(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ srcval = fetch_data_word(srcoffset);
+ CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+ for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
+ if ((srcval >> *dstreg) & 1) break;
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval, *dstreg;
+
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ srcval = fetch_data_long(srcoffset);
+ CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+ for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
+ if ((srcval >> *dstreg) & 1) break;
+ } else {
+ u16 srcval, *dstreg;
+
+ srcoffset = decode_rm01_address(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ srcval = fetch_data_word(srcoffset);
+ CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+ for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
+ if ((srcval >> *dstreg) & 1) break;
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 srcval, *dstreg;
+
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ srcval = fetch_data_long(srcoffset);
+ CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+ for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
+ if ((srcval >> *dstreg) & 1) break;
+ } else {
+ u16 srcval, *dstreg;
+
+ srcoffset = decode_rm10_address(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ srcval = fetch_data_word(srcoffset);
+ CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
+ for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
+ if ((srcval >> *dstreg) & 1) break;
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *srcreg, *dstreg;
+
+ srcreg = DECODE_RM_LONG_REGISTER(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_LONG_REGISTER(rh);
+ TRACE_AND_STEP();
+ CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
+ for(*dstreg = 31; *dstreg > 0; (*dstreg)--)
+ if ((*srcreg >> *dstreg) & 1) break;
+ } else {
+ u16 *srcreg, *dstreg;
+
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF(",");
+ dstreg = DECODE_RM_WORD_REGISTER(rh);
+ TRACE_AND_STEP();
+ CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF);
+ for(*dstreg = 15; *dstreg > 0; (*dstreg)--)
+ if ((*srcreg >> *dstreg) & 1) break;
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbe
+****************************************************************************/
+void x86emuOp2_movsx_byte_R_RM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOVSX\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = (s32)((s8)fetch_data_byte(srcoffset));
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = (s16)((s8)fetch_data_byte(srcoffset));
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ }
+ break;
+ case 1:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = (s32)((s8)fetch_data_byte(srcoffset));
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = (s16)((s8)fetch_data_byte(srcoffset));
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ }
+ break;
+ case 2:
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u32 srcval;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = (s32)((s8)fetch_data_byte(srcoffset));
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ } else {
+ u16 *destreg;
+ u16 srcval;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = (s16)((s8)fetch_data_byte(srcoffset));
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ }
+ break;
+ case 3: /* register to register */
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ u32 *destreg;
+ u8 *srcreg;
+
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = (s32)((s8)*srcreg);
+ } else {
+ u16 *destreg;
+ u8 *srcreg;
+
+ destreg = DECODE_RM_WORD_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_BYTE_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = (s16)((s8)*srcreg);
+ }
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/****************************************************************************
+REMARKS:
+Handles opcode 0x0f,0xbf
+****************************************************************************/
+void x86emuOp2_movsx_word_R_RM(u8 X86EMU_UNUSED(op2))
+{
+ int mod, rl, rh;
+ uint srcoffset;
+ u32 *destreg;
+ u32 srcval;
+ u16 *srcreg;
+
+ START_OF_INSTR();
+ DECODE_PRINTF("MOVSX\t");
+ FETCH_DECODE_MODRM(mod, rh, rl);
+ switch (mod) {
+ case 0:
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm00_address(rl);
+ srcval = (s32)((s16)fetch_data_word(srcoffset));
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 1:
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm01_address(rl);
+ srcval = (s32)((s16)fetch_data_word(srcoffset));
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 2:
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcoffset = decode_rm10_address(rl);
+ srcval = (s32)((s16)fetch_data_word(srcoffset));
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = srcval;
+ break;
+ case 3: /* register to register */
+ destreg = DECODE_RM_LONG_REGISTER(rh);
+ DECODE_PRINTF(",");
+ srcreg = DECODE_RM_WORD_REGISTER(rl);
+ DECODE_PRINTF("\n");
+ TRACE_AND_STEP();
+ *destreg = (s32)((s16)*srcreg);
+ break;
+ }
+ DECODE_CLEAR_SEGOVR();
+ END_OF_INSTR();
+}
+
+/***************************************************************************
+ * Double byte operation code table:
+ **************************************************************************/
+void (*x86emu_optab2[256])(u8) =
+{
+/* 0x00 */ x86emuOp2_illegal_op, /* Group F (ring 0 PM) */
+/* 0x01 */ x86emuOp2_illegal_op, /* Group G (ring 0 PM) */
+/* 0x02 */ x86emuOp2_illegal_op, /* lar (ring 0 PM) */
+/* 0x03 */ x86emuOp2_illegal_op, /* lsl (ring 0 PM) */
+/* 0x04 */ x86emuOp2_illegal_op,
+/* 0x05 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
+/* 0x06 */ x86emuOp2_illegal_op, /* clts (ring 0 PM) */
+/* 0x07 */ x86emuOp2_illegal_op, /* loadall (undocumented) */
+/* 0x08 */ x86emuOp2_illegal_op, /* invd (ring 0 PM) */
+/* 0x09 */ x86emuOp2_illegal_op, /* wbinvd (ring 0 PM) */
+/* 0x0a */ x86emuOp2_illegal_op,
+/* 0x0b */ x86emuOp2_illegal_op,
+/* 0x0c */ x86emuOp2_illegal_op,
+/* 0x0d */ x86emuOp2_illegal_op,
+/* 0x0e */ x86emuOp2_illegal_op,
+/* 0x0f */ x86emuOp2_illegal_op,
+
+/* 0x10 */ x86emuOp2_illegal_op,
+/* 0x11 */ x86emuOp2_illegal_op,
+/* 0x12 */ x86emuOp2_illegal_op,
+/* 0x13 */ x86emuOp2_illegal_op,
+/* 0x14 */ x86emuOp2_illegal_op,
+/* 0x15 */ x86emuOp2_illegal_op,
+/* 0x16 */ x86emuOp2_illegal_op,
+/* 0x17 */ x86emuOp2_illegal_op,
+/* 0x18 */ x86emuOp2_illegal_op,
+/* 0x19 */ x86emuOp2_illegal_op,
+/* 0x1a */ x86emuOp2_illegal_op,
+/* 0x1b */ x86emuOp2_illegal_op,
+/* 0x1c */ x86emuOp2_illegal_op,
+/* 0x1d */ x86emuOp2_illegal_op,
+/* 0x1e */ x86emuOp2_illegal_op,
+/* 0x1f */ x86emuOp2_illegal_op,
+
+/* 0x20 */ x86emuOp2_illegal_op, /* mov reg32,creg (ring 0 PM) */
+/* 0x21 */ x86emuOp2_illegal_op, /* mov reg32,dreg (ring 0 PM) */
+/* 0x22 */ x86emuOp2_illegal_op, /* mov creg,reg32 (ring 0 PM) */
+/* 0x23 */ x86emuOp2_illegal_op, /* mov dreg,reg32 (ring 0 PM) */
+/* 0x24 */ x86emuOp2_illegal_op, /* mov reg32,treg (ring 0 PM) */
+/* 0x25 */ x86emuOp2_illegal_op,
+/* 0x26 */ x86emuOp2_illegal_op, /* mov treg,reg32 (ring 0 PM) */
+/* 0x27 */ x86emuOp2_illegal_op,
+/* 0x28 */ x86emuOp2_illegal_op,
+/* 0x29 */ x86emuOp2_illegal_op,
+/* 0x2a */ x86emuOp2_illegal_op,
+/* 0x2b */ x86emuOp2_illegal_op,
+/* 0x2c */ x86emuOp2_illegal_op,
+/* 0x2d */ x86emuOp2_illegal_op,
+/* 0x2e */ x86emuOp2_illegal_op,
+/* 0x2f */ x86emuOp2_illegal_op,
+
+/* 0x30 */ x86emuOp2_illegal_op,
+/* 0x31 */ x86emuOp2_illegal_op,
+/* 0x32 */ x86emuOp2_illegal_op,
+/* 0x33 */ x86emuOp2_illegal_op,
+/* 0x34 */ x86emuOp2_illegal_op,
+/* 0x35 */ x86emuOp2_illegal_op,
+/* 0x36 */ x86emuOp2_illegal_op,
+/* 0x37 */ x86emuOp2_illegal_op,
+/* 0x38 */ x86emuOp2_illegal_op,
+/* 0x39 */ x86emuOp2_illegal_op,
+/* 0x3a */ x86emuOp2_illegal_op,
+/* 0x3b */ x86emuOp2_illegal_op,
+/* 0x3c */ x86emuOp2_illegal_op,
+/* 0x3d */ x86emuOp2_illegal_op,
+/* 0x3e */ x86emuOp2_illegal_op,
+/* 0x3f */ x86emuOp2_illegal_op,
+
+/* 0x40 */ x86emuOp2_illegal_op,
+/* 0x41 */ x86emuOp2_illegal_op,
+/* 0x42 */ x86emuOp2_illegal_op,
+/* 0x43 */ x86emuOp2_illegal_op,
+/* 0x44 */ x86emuOp2_illegal_op,
+/* 0x45 */ x86emuOp2_illegal_op,
+/* 0x46 */ x86emuOp2_illegal_op,
+/* 0x47 */ x86emuOp2_illegal_op,
+/* 0x48 */ x86emuOp2_illegal_op,
+/* 0x49 */ x86emuOp2_illegal_op,
+/* 0x4a */ x86emuOp2_illegal_op,
+/* 0x4b */ x86emuOp2_illegal_op,
+/* 0x4c */ x86emuOp2_illegal_op,
+/* 0x4d */ x86emuOp2_illegal_op,
+/* 0x4e */ x86emuOp2_illegal_op,
+/* 0x4f */ x86emuOp2_illegal_op,
+
+/* 0x50 */ x86emuOp2_illegal_op,
+/* 0x51 */ x86emuOp2_illegal_op,
+/* 0x52 */ x86emuOp2_illegal_op,
+/* 0x53 */ x86emuOp2_illegal_op,
+/* 0x54 */ x86emuOp2_illegal_op,
+/* 0x55 */ x86emuOp2_illegal_op,
+/* 0x56 */ x86emuOp2_illegal_op,
+/* 0x57 */ x86emuOp2_illegal_op,
+/* 0x58 */ x86emuOp2_illegal_op,
+/* 0x59 */ x86emuOp2_illegal_op,
+/* 0x5a */ x86emuOp2_illegal_op,
+/* 0x5b */ x86emuOp2_illegal_op,
+/* 0x5c */ x86emuOp2_illegal_op,
+/* 0x5d */ x86emuOp2_illegal_op,
+/* 0x5e */ x86emuOp2_illegal_op,
+/* 0x5f */ x86emuOp2_illegal_op,
+
+/* 0x60 */ x86emuOp2_illegal_op,
+/* 0x61 */ x86emuOp2_illegal_op,
+/* 0x62 */ x86emuOp2_illegal_op,
+/* 0x63 */ x86emuOp2_illegal_op,
+/* 0x64 */ x86emuOp2_illegal_op,
+/* 0x65 */ x86emuOp2_illegal_op,
+/* 0x66 */ x86emuOp2_illegal_op,
+/* 0x67 */ x86emuOp2_illegal_op,
+/* 0x68 */ x86emuOp2_illegal_op,
+/* 0x69 */ x86emuOp2_illegal_op,
+/* 0x6a */ x86emuOp2_illegal_op,
+/* 0x6b */ x86emuOp2_illegal_op,
+/* 0x6c */ x86emuOp2_illegal_op,
+/* 0x6d */ x86emuOp2_illegal_op,
+/* 0x6e */ x86emuOp2_illegal_op,
+/* 0x6f */ x86emuOp2_illegal_op,
+
+/* 0x70 */ x86emuOp2_illegal_op,
+/* 0x71 */ x86emuOp2_illegal_op,
+/* 0x72 */ x86emuOp2_illegal_op,
+/* 0x73 */ x86emuOp2_illegal_op,
+/* 0x74 */ x86emuOp2_illegal_op,
+/* 0x75 */ x86emuOp2_illegal_op,
+/* 0x76 */ x86emuOp2_illegal_op,
+/* 0x77 */ x86emuOp2_illegal_op,
+/* 0x78 */ x86emuOp2_illegal_op,
+/* 0x79 */ x86emuOp2_illegal_op,
+/* 0x7a */ x86emuOp2_illegal_op,
+/* 0x7b */ x86emuOp2_illegal_op,
+/* 0x7c */ x86emuOp2_illegal_op,
+/* 0x7d */ x86emuOp2_illegal_op,
+/* 0x7e */ x86emuOp2_illegal_op,
+/* 0x7f */ x86emuOp2_illegal_op,
+
+/* 0x80 */ x86emuOp2_long_jump,
+/* 0x81 */ x86emuOp2_long_jump,
+/* 0x82 */ x86emuOp2_long_jump,
+/* 0x83 */ x86emuOp2_long_jump,
+/* 0x84 */ x86emuOp2_long_jump,
+/* 0x85 */ x86emuOp2_long_jump,
+/* 0x86 */ x86emuOp2_long_jump,
+/* 0x87 */ x86emuOp2_long_jump,
+/* 0x88 */ x86emuOp2_long_jump,
+/* 0x89 */ x86emuOp2_long_jump,
+/* 0x8a */ x86emuOp2_long_jump,
+/* 0x8b */ x86emuOp2_long_jump,
+/* 0x8c */ x86emuOp2_long_jump,
+/* 0x8d */ x86emuOp2_long_jump,
+/* 0x8e */ x86emuOp2_long_jump,
+/* 0x8f */ x86emuOp2_long_jump,
+
+/* 0x90 */ x86emuOp2_set_byte,
+/* 0x91 */ x86emuOp2_set_byte,
+/* 0x92 */ x86emuOp2_set_byte,
+/* 0x93 */ x86emuOp2_set_byte,
+/* 0x94 */ x86emuOp2_set_byte,
+/* 0x95 */ x86emuOp2_set_byte,
+/* 0x96 */ x86emuOp2_set_byte,
+/* 0x97 */ x86emuOp2_set_byte,
+/* 0x98 */ x86emuOp2_set_byte,
+/* 0x99 */ x86emuOp2_set_byte,
+/* 0x9a */ x86emuOp2_set_byte,
+/* 0x9b */ x86emuOp2_set_byte,
+/* 0x9c */ x86emuOp2_set_byte,
+/* 0x9d */ x86emuOp2_set_byte,
+/* 0x9e */ x86emuOp2_set_byte,
+/* 0x9f */ x86emuOp2_set_byte,
+
+/* 0xa0 */ x86emuOp2_push_FS,
+/* 0xa1 */ x86emuOp2_pop_FS,
+/* 0xa2 */ x86emuOp2_illegal_op,
+/* 0xa3 */ x86emuOp2_bt_R,
+/* 0xa4 */ x86emuOp2_shld_IMM,
+/* 0xa5 */ x86emuOp2_shld_CL,
+/* 0xa6 */ x86emuOp2_illegal_op,
+/* 0xa7 */ x86emuOp2_illegal_op,
+/* 0xa8 */ x86emuOp2_push_GS,
+/* 0xa9 */ x86emuOp2_pop_GS,
+/* 0xaa */ x86emuOp2_illegal_op,
+/* 0xab */ x86emuOp2_bt_R,
+/* 0xac */ x86emuOp2_shrd_IMM,
+/* 0xad */ x86emuOp2_shrd_CL,
+/* 0xae */ x86emuOp2_illegal_op,
+/* 0xaf */ x86emuOp2_imul_R_RM,
+
+/* 0xb0 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
+/* 0xb1 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */
+/* 0xb2 */ x86emuOp2_lss_R_IMM,
+/* 0xb3 */ x86emuOp2_btr_R,
+/* 0xb4 */ x86emuOp2_lfs_R_IMM,
+/* 0xb5 */ x86emuOp2_lgs_R_IMM,
+/* 0xb6 */ x86emuOp2_movzx_byte_R_RM,
+/* 0xb7 */ x86emuOp2_movzx_word_R_RM,
+/* 0xb8 */ x86emuOp2_illegal_op,
+/* 0xb9 */ x86emuOp2_illegal_op,
+/* 0xba */ x86emuOp2_btX_I,
+/* 0xbb */ x86emuOp2_btc_R,
+/* 0xbc */ x86emuOp2_bsf,
+/* 0xbd */ x86emuOp2_bsr,
+/* 0xbe */ x86emuOp2_movsx_byte_R_RM,
+/* 0xbf */ x86emuOp2_movsx_word_R_RM,
+
+/* 0xc0 */ x86emuOp2_illegal_op, /* TODO: xadd */
+/* 0xc1 */ x86emuOp2_illegal_op, /* TODO: xadd */
+/* 0xc2 */ x86emuOp2_illegal_op,
+/* 0xc3 */ x86emuOp2_illegal_op,
+/* 0xc4 */ x86emuOp2_illegal_op,
+/* 0xc5 */ x86emuOp2_illegal_op,
+/* 0xc6 */ x86emuOp2_illegal_op,
+/* 0xc7 */ x86emuOp2_illegal_op,
+/* 0xc8 */ x86emuOp2_illegal_op, /* TODO: bswap */
+/* 0xc9 */ x86emuOp2_illegal_op, /* TODO: bswap */
+/* 0xca */ x86emuOp2_illegal_op, /* TODO: bswap */
+/* 0xcb */ x86emuOp2_illegal_op, /* TODO: bswap */
+/* 0xcc */ x86emuOp2_illegal_op, /* TODO: bswap */
+/* 0xcd */ x86emuOp2_illegal_op, /* TODO: bswap */
+/* 0xce */ x86emuOp2_illegal_op, /* TODO: bswap */
+/* 0xcf */ x86emuOp2_illegal_op, /* TODO: bswap */
+
+/* 0xd0 */ x86emuOp2_illegal_op,
+/* 0xd1 */ x86emuOp2_illegal_op,
+/* 0xd2 */ x86emuOp2_illegal_op,
+/* 0xd3 */ x86emuOp2_illegal_op,
+/* 0xd4 */ x86emuOp2_illegal_op,
+/* 0xd5 */ x86emuOp2_illegal_op,
+/* 0xd6 */ x86emuOp2_illegal_op,
+/* 0xd7 */ x86emuOp2_illegal_op,
+/* 0xd8 */ x86emuOp2_illegal_op,
+/* 0xd9 */ x86emuOp2_illegal_op,
+/* 0xda */ x86emuOp2_illegal_op,
+/* 0xdb */ x86emuOp2_illegal_op,
+/* 0xdc */ x86emuOp2_illegal_op,
+/* 0xdd */ x86emuOp2_illegal_op,
+/* 0xde */ x86emuOp2_illegal_op,
+/* 0xdf */ x86emuOp2_illegal_op,
+
+/* 0xe0 */ x86emuOp2_illegal_op,
+/* 0xe1 */ x86emuOp2_illegal_op,
+/* 0xe2 */ x86emuOp2_illegal_op,
+/* 0xe3 */ x86emuOp2_illegal_op,
+/* 0xe4 */ x86emuOp2_illegal_op,
+/* 0xe5 */ x86emuOp2_illegal_op,
+/* 0xe6 */ x86emuOp2_illegal_op,
+/* 0xe7 */ x86emuOp2_illegal_op,
+/* 0xe8 */ x86emuOp2_illegal_op,
+/* 0xe9 */ x86emuOp2_illegal_op,
+/* 0xea */ x86emuOp2_illegal_op,
+/* 0xeb */ x86emuOp2_illegal_op,
+/* 0xec */ x86emuOp2_illegal_op,
+/* 0xed */ x86emuOp2_illegal_op,
+/* 0xee */ x86emuOp2_illegal_op,
+/* 0xef */ x86emuOp2_illegal_op,
+
+/* 0xf0 */ x86emuOp2_illegal_op,
+/* 0xf1 */ x86emuOp2_illegal_op,
+/* 0xf2 */ x86emuOp2_illegal_op,
+/* 0xf3 */ x86emuOp2_illegal_op,
+/* 0xf4 */ x86emuOp2_illegal_op,
+/* 0xf5 */ x86emuOp2_illegal_op,
+/* 0xf6 */ x86emuOp2_illegal_op,
+/* 0xf7 */ x86emuOp2_illegal_op,
+/* 0xf8 */ x86emuOp2_illegal_op,
+/* 0xf9 */ x86emuOp2_illegal_op,
+/* 0xfa */ x86emuOp2_illegal_op,
+/* 0xfb */ x86emuOp2_illegal_op,
+/* 0xfc */ x86emuOp2_illegal_op,
+/* 0xfd */ x86emuOp2_illegal_op,
+/* 0xfe */ x86emuOp2_illegal_op,
+/* 0xff */ x86emuOp2_illegal_op,
+};
diff --git a/cfe/cfe/x86emu/prim_ops.c b/cfe/cfe/x86emu/prim_ops.c
new file mode 100644
index 0000000..dca16cd
--- /dev/null
+++ b/cfe/cfe/x86emu/prim_ops.c
@@ -0,0 +1,2915 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: This file contains the code to implement the primitive
+* machine operations used by the emulation code in ops.c
+*
+* Carry Chain Calculation
+*
+* This represents a somewhat expensive calculation which is
+* apparently required to emulate the setting of the OF and AF flag.
+* The latter is not so important, but the former is. The overflow
+* flag is the XOR of the top two bits of the carry chain for an
+* addition (similar for subtraction). Since we do not want to
+* simulate the addition in a bitwise manner, we try to calculate the
+* carry chain given the two operands and the result.
+*
+* So, given the following table, which represents the addition of two
+* bits, we can derive a formula for the carry chain.
+*
+* a b cin r cout
+* 0 0 0 0 0
+* 0 0 1 1 0
+* 0 1 0 1 0
+* 0 1 1 0 1
+* 1 0 0 1 0
+* 1 0 1 0 1
+* 1 1 0 0 1
+* 1 1 1 1 1
+*
+* Construction of table for cout:
+*
+* ab
+* r \ 00 01 11 10
+* |------------------
+* 0 | 0 1 1 1
+* 1 | 0 0 1 0
+*
+* By inspection, one gets: cc = ab + r'(a + b)
+*
+* That represents alot of operations, but NO CHOICE....
+*
+* Borrow Chain Calculation.
+*
+* The following table represents the subtraction of two bits, from
+* which we can derive a formula for the borrow chain.
+*
+* a b bin r bout
+* 0 0 0 0 0
+* 0 0 1 1 1
+* 0 1 0 1 1
+* 0 1 1 0 1
+* 1 0 0 1 0
+* 1 0 1 0 0
+* 1 1 0 0 0
+* 1 1 1 1 1
+*
+* Construction of table for cout:
+*
+* ab
+* r \ 00 01 11 10
+* |------------------
+* 0 | 0 1 0 0
+* 1 | 1 1 1 0
+*
+* By inspection, one gets: bc = a'b + r(a' + b)
+*
+****************************************************************************/
+
+#define PRIM_OPS_NO_REDEFINE_ASM
+#include "x86emu/x86emui.h"
+
+/*------------------------- Global Variables ------------------------------*/
+
+#ifndef __HAVE_INLINE_ASSEMBLER__
+
+static u32 x86emu_parity_tab[8] =
+{
+ 0x96696996,
+ 0x69969669,
+ 0x69969669,
+ 0x96696996,
+ 0x69969669,
+ 0x96696996,
+ 0x96696996,
+ 0x69969669,
+};
+
+#endif
+
+#define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
+#define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
+
+/*----------------------------- Implementation ----------------------------*/
+
+#ifndef __HAVE_INLINE_ASSEMBLER__
+
+/****************************************************************************
+REMARKS:
+Implements the AAA instruction and side effects.
+****************************************************************************/
+u16 aaa_word(u16 d)
+{
+ u16 res;
+ if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
+ d += 0x6;
+ d += 0x100;
+ SET_FLAG(F_AF);
+ SET_FLAG(F_CF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ }
+ res = (u16)(d & 0xFF0F);
+ CLEAR_FLAG(F_SF);
+ CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AAA instruction and side effects.
+****************************************************************************/
+u16 aas_word(u16 d)
+{
+ u16 res;
+ if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
+ d -= 0x6;
+ d -= 0x100;
+ SET_FLAG(F_AF);
+ SET_FLAG(F_CF);
+ } else {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ }
+ res = (u16)(d & 0xFF0F);
+ CLEAR_FLAG(F_SF);
+ CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AAD instruction and side effects.
+****************************************************************************/
+u16 aad_word(u16 d)
+{
+ u16 l;
+ u8 hb, lb;
+
+ hb = (u8)((d >> 8) & 0xff);
+ lb = (u8)((d & 0xff));
+ l = (u16)((lb + 10 * hb) & 0xFF);
+
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ CLEAR_FLAG(F_OF);
+ CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG(l == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
+ return l;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AAM instruction and side effects.
+****************************************************************************/
+u16 aam_word(u8 d)
+{
+ u16 h, l;
+
+ h = (u16)(d / 10);
+ l = (u16)(d % 10);
+ l |= (u16)(h << 8);
+
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ CLEAR_FLAG(F_OF);
+ CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG(l == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
+ return l;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADC instruction and side effects.
+****************************************************************************/
+u8 adc_byte(u8 d, u8 s)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 cc;
+
+ if (ACCESS_FLAG(F_CF))
+ res = 1 + d + s;
+ else
+ res = d + s;
+
+ CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
+ CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the carry chain SEE NOTE AT TOP. */
+ cc = (s & d) | ((~res) & (s | d));
+ CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
+ CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADC instruction and side effects.
+****************************************************************************/
+u16 adc_word(u16 d, u16 s)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 cc;
+
+ if (ACCESS_FLAG(F_CF))
+ res = 1 + d + s;
+ else
+ res = d + s;
+
+ CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
+ CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the carry chain SEE NOTE AT TOP. */
+ cc = (s & d) | ((~res) & (s | d));
+ CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
+ CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADC instruction and side effects.
+****************************************************************************/
+u32 adc_long(u32 d, u32 s)
+{
+ register u32 lo; /* all operands in native machine order */
+ register u32 hi;
+ register u32 res;
+ register u32 cc;
+
+ if (ACCESS_FLAG(F_CF)) {
+ lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
+ res = 1 + d + s;
+ }
+ else {
+ lo = (d & 0xFFFF) + (s & 0xFFFF);
+ res = d + s;
+ }
+ hi = (lo >> 16) + (d >> 16) + (s >> 16);
+
+ CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
+ CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the carry chain SEE NOTE AT TOP. */
+ cc = (s & d) | ((~res) & (s | d));
+ CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
+ CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADD instruction and side effects.
+****************************************************************************/
+u8 add_byte(u8 d, u8 s)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 cc;
+
+ res = d + s;
+ CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
+ CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the carry chain SEE NOTE AT TOP. */
+ cc = (s & d) | ((~res) & (s | d));
+ CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
+ CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADD instruction and side effects.
+****************************************************************************/
+u16 add_word(u16 d, u16 s)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 cc;
+
+ res = d + s;
+ CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
+ CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the carry chain SEE NOTE AT TOP. */
+ cc = (s & d) | ((~res) & (s | d));
+ CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
+ CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ADD instruction and side effects.
+****************************************************************************/
+u32 add_long(u32 d, u32 s)
+{
+ register u32 lo; /* all operands in native machine order */
+ register u32 hi;
+ register u32 res;
+ register u32 cc;
+
+ lo = (d & 0xFFFF) + (s & 0xFFFF);
+ res = d + s;
+ hi = (lo >> 16) + (d >> 16) + (s >> 16);
+
+ CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
+ CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the carry chain SEE NOTE AT TOP. */
+ cc = (s & d) | ((~res) & (s | d));
+ CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
+ CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AND instruction and side effects.
+****************************************************************************/
+u8 and_byte(u8 d, u8 s)
+{
+ register u8 res; /* all operands in native machine order */
+
+ res = d & s;
+
+ /* set the flags */
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AND instruction and side effects.
+****************************************************************************/
+u16 and_word(u16 d, u16 s)
+{
+ register u16 res; /* all operands in native machine order */
+
+ res = d & s;
+
+ /* set the flags */
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the AND instruction and side effects.
+****************************************************************************/
+u32 and_long(u32 d, u32 s)
+{
+ register u32 res; /* all operands in native machine order */
+
+ res = d & s;
+
+ /* set the flags */
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the CMP instruction and side effects.
+****************************************************************************/
+u8 cmp_byte(u8 d, u8 s)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 bc;
+
+ res = d - s;
+ CLEAR_FLAG(F_CF);
+ CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the borrow chain. See note at top */
+ bc = (res & (~d | s)) | (~d & s);
+ CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return d;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the CMP instruction and side effects.
+****************************************************************************/
+u16 cmp_word(u16 d, u16 s)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 bc;
+
+ res = d - s;
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the borrow chain. See note at top */
+ bc = (res & (~d | s)) | (~d & s);
+ CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return d;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the CMP instruction and side effects.
+****************************************************************************/
+u32 cmp_long(u32 d, u32 s)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 bc;
+
+ res = d - s;
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the borrow chain. See note at top */
+ bc = (res & (~d | s)) | (~d & s);
+ CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return d;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DAA instruction and side effects.
+****************************************************************************/
+u8 daa_byte(u8 d)
+{
+ u32 res = d;
+ if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
+ res += 6;
+ SET_FLAG(F_AF);
+ }
+ if (res > 0x9F || ACCESS_FLAG(F_CF)) {
+ res += 0x60;
+ SET_FLAG(F_CF);
+ }
+ CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DAS instruction and side effects.
+****************************************************************************/
+u8 das_byte(u8 d)
+{
+ if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
+ d -= 6;
+ SET_FLAG(F_AF);
+ }
+ if (d > 0x9F || ACCESS_FLAG(F_CF)) {
+ d -= 0x60;
+ SET_FLAG(F_CF);
+ }
+ CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG(d == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
+ return d;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DEC instruction and side effects.
+****************************************************************************/
+u8 dec_byte(u8 d)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 bc;
+
+ res = d - 1;
+ CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the borrow chain. See note at top */
+ /* based on sub_byte, uses s==1. */
+ bc = (res & (~d | 1)) | (~d & 1);
+ /* carry flag unchanged */
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DEC instruction and side effects.
+****************************************************************************/
+u16 dec_word(u16 d)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 bc;
+
+ res = d - 1;
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the borrow chain. See note at top */
+ /* based on the sub_byte routine, with s==1 */
+ bc = (res & (~d | 1)) | (~d & 1);
+ /* carry flag unchanged */
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DEC instruction and side effects.
+****************************************************************************/
+u32 dec_long(u32 d)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 bc;
+
+ res = d - 1;
+
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the borrow chain. See note at top */
+ bc = (res & (~d | 1)) | (~d & 1);
+ /* carry flag unchanged */
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the INC instruction and side effects.
+****************************************************************************/
+u8 inc_byte(u8 d)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 cc;
+
+ res = d + 1;
+ CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the carry chain SEE NOTE AT TOP. */
+ cc = ((1 & d) | (~res)) & (1 | d);
+ CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
+ CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the INC instruction and side effects.
+****************************************************************************/
+u16 inc_word(u16 d)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 cc;
+
+ res = d + 1;
+ CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the carry chain SEE NOTE AT TOP. */
+ cc = (1 & d) | ((~res) & (1 | d));
+ CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
+ CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the INC instruction and side effects.
+****************************************************************************/
+u32 inc_long(u32 d)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 cc;
+
+ res = d + 1;
+ CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the carry chain SEE NOTE AT TOP. */
+ cc = (1 & d) | ((~res) & (1 | d));
+ CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
+ CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u8 or_byte(u8 d, u8 s)
+{
+ register u8 res; /* all operands in native machine order */
+
+ res = d | s;
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u16 or_word(u16 d, u16 s)
+{
+ register u16 res; /* all operands in native machine order */
+
+ res = d | s;
+ /* set the carry flag to be bit 8 */
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u32 or_long(u32 d, u32 s)
+{
+ register u32 res; /* all operands in native machine order */
+
+ res = d | s;
+
+ /* set the carry flag to be bit 8 */
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u8 neg_byte(u8 s)
+{
+ register u8 res;
+ register u8 bc;
+
+ CONDITIONAL_SET_FLAG(s != 0, F_CF);
+ res = (u8)-s;
+ CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
+ /* calculate the borrow chain --- modified such that d=0.
+ substitutiing d=0 into bc= res&(~d|s)|(~d&s);
+ (the one used for sub) and simplifying, since ~d=0xff...,
+ ~d|s == 0xffff..., and res&0xfff... == res. Similarly
+ ~d&s == s. So the simplified result is: */
+ bc = res | s;
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u16 neg_word(u16 s)
+{
+ register u16 res;
+ register u16 bc;
+
+ CONDITIONAL_SET_FLAG(s != 0, F_CF);
+ res = (u16)-s;
+ CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the borrow chain --- modified such that d=0.
+ substitutiing d=0 into bc= res&(~d|s)|(~d&s);
+ (the one used for sub) and simplifying, since ~d=0xff...,
+ ~d|s == 0xffff..., and res&0xfff... == res. Similarly
+ ~d&s == s. So the simplified result is: */
+ bc = res | s;
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OR instruction and side effects.
+****************************************************************************/
+u32 neg_long(u32 s)
+{
+ register u32 res;
+ register u32 bc;
+
+ CONDITIONAL_SET_FLAG(s != 0, F_CF);
+ res = (u32)-s;
+ CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the borrow chain --- modified such that d=0.
+ substitutiing d=0 into bc= res&(~d|s)|(~d&s);
+ (the one used for sub) and simplifying, since ~d=0xff...,
+ ~d|s == 0xffff..., and res&0xfff... == res. Similarly
+ ~d&s == s. So the simplified result is: */
+ bc = res | s;
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the NOT instruction and side effects.
+****************************************************************************/
+u8 not_byte(u8 s)
+{
+ return ~s;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the NOT instruction and side effects.
+****************************************************************************/
+u16 not_word(u16 s)
+{
+ return ~s;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the NOT instruction and side effects.
+****************************************************************************/
+u32 not_long(u32 s)
+{
+ return ~s;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCL instruction and side effects.
+****************************************************************************/
+u8 rcl_byte(u8 d, u8 s)
+{
+ register unsigned int res, cnt, mask, cf;
+
+ /* s is the rotate distance. It varies from 0 - 8. */
+ /* have
+
+ CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
+
+ want to rotate through the carry by "s" bits. We could
+ loop, but that's inefficient. So the width is 9,
+ and we split into three parts:
+
+ The new carry flag (was B_n)
+ the stuff in B_n-1 .. B_0
+ the stuff in B_7 .. B_n+1
+
+ The new rotate is done mod 9, and given this,
+ for a rotation of n bits (mod 9) the new carry flag is
+ then located n bits from the MSB. The low part is
+ then shifted up cnt bits, and the high part is or'd
+ in. Using CAPS for new values, and lowercase for the
+ original values, this can be expressed as:
+
+ IF n > 0
+ 1) CF <- b_(8-n)
+ 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
+ 3) B_(n-1) <- cf
+ 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
+ */
+ res = d;
+ if ((cnt = s % 9) != 0) {
+ /* extract the new CARRY FLAG. */
+ /* CF <- b_(8-n) */
+ cf = (d >> (8 - cnt)) & 0x1;
+
+ /* get the low stuff which rotated
+ into the range B_7 .. B_cnt */
+ /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
+ /* note that the right hand side done by the mask */
+ res = (d << cnt) & 0xff;
+
+ /* now the high stuff which rotated around
+ into the positions B_cnt-2 .. B_0 */
+ /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
+ /* shift it downward, 7-(n-2) = 9-n positions.
+ and mask off the result before or'ing in.
+ */
+ mask = (1 << (cnt - 1)) - 1;
+ res |= (d >> (9 - cnt)) & mask;
+
+ /* if the carry flag was set, or it in. */
+ if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
+ /* B_(n-1) <- cf */
+ res |= 1 << (cnt - 1);
+ }
+ /* set the new carry flag, based on the variable "cf" */
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ /* OVERFLOW is set *IFF* cnt==1, then it is the
+ xor of CF and the most significant bit. Blecck. */
+ /* parenthesized this expression since it appears to
+ be causing OF to be misset */
+ CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
+ F_OF);
+
+ }
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCL instruction and side effects.
+****************************************************************************/
+u16 rcl_word(u16 d, u8 s)
+{
+ register unsigned int res, cnt, mask, cf;
+
+ res = d;
+ if ((cnt = s % 17) != 0) {
+ cf = (d >> (16 - cnt)) & 0x1;
+ res = (d << cnt) & 0xffff;
+ mask = (1 << (cnt - 1)) - 1;
+ res |= (d >> (17 - cnt)) & mask;
+ if (ACCESS_FLAG(F_CF)) {
+ res |= 1 << (cnt - 1);
+ }
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
+ F_OF);
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCL instruction and side effects.
+****************************************************************************/
+u32 rcl_long(u32 d, u8 s)
+{
+ register u32 res, cnt, mask, cf;
+
+ res = d;
+ if ((cnt = s % 33) != 0) {
+ cf = (d >> (32 - cnt)) & 0x1;
+ res = (d << cnt) & 0xffffffff;
+ mask = (1 << (cnt - 1)) - 1;
+ res |= (d >> (33 - cnt)) & mask;
+ if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
+ res |= 1 << (cnt - 1);
+ }
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
+ F_OF);
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCR instruction and side effects.
+****************************************************************************/
+u8 rcr_byte(u8 d, u8 s)
+{
+ u32 res, cnt;
+ u32 mask, cf, ocf = 0;
+
+ /* rotate right through carry */
+ /*
+ s is the rotate distance. It varies from 0 - 8.
+ d is the byte object rotated.
+
+ have
+
+ CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
+
+ The new rotate is done mod 9, and given this,
+ for a rotation of n bits (mod 9) the new carry flag is
+ then located n bits from the LSB. The low part is
+ then shifted up cnt bits, and the high part is or'd
+ in. Using CAPS for new values, and lowercase for the
+ original values, this can be expressed as:
+
+ IF n > 0
+ 1) CF <- b_(n-1)
+ 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
+ 3) B_(8-n) <- cf
+ 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0)
+ */
+ res = d;
+ if ((cnt = s % 9) != 0) {
+ /* extract the new CARRY FLAG. */
+ /* CF <- b_(n-1) */
+ if (cnt == 1) {
+ cf = d & 0x1;
+ /* note hackery here. Access_flag(..) evaluates to either
+ 0 if flag not set
+ non-zero if flag is set.
+ doing access_flag(..) != 0 casts that into either
+ 0..1 in any representation of the flags register
+ (i.e. packed bit array or unpacked.)
+ */
+ ocf = ACCESS_FLAG(F_CF) != 0;
+ } else
+ cf = (d >> (cnt - 1)) & 0x1;
+
+ /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
+ /* note that the right hand side done by the mask
+ This is effectively done by shifting the
+ object to the right. The result must be masked,
+ in case the object came in and was treated
+ as a negative number. Needed??? */
+
+ mask = (1 << (8 - cnt)) - 1;
+ res = (d >> cnt) & mask;
+
+ /* now the high stuff which rotated around
+ into the positions B_cnt-2 .. B_0 */
+ /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
+ /* shift it downward, 7-(n-2) = 9-n positions.
+ and mask off the result before or'ing in.
+ */
+ res |= (d << (9 - cnt));
+
+ /* if the carry flag was set, or it in. */
+ if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
+ /* B_(8-n) <- cf */
+ res |= 1 << (8 - cnt);
+ }
+ /* set the new carry flag, based on the variable "cf" */
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ /* OVERFLOW is set *IFF* cnt==1, then it is the
+ xor of CF and the most significant bit. Blecck. */
+ /* parenthesized... */
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
+ F_OF);
+ }
+ }
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCR instruction and side effects.
+****************************************************************************/
+u16 rcr_word(u16 d, u8 s)
+{
+ u32 res, cnt;
+ u32 mask, cf, ocf = 0;
+
+ /* rotate right through carry */
+ res = d;
+ if ((cnt = s % 17) != 0) {
+ if (cnt == 1) {
+ cf = d & 0x1;
+ ocf = ACCESS_FLAG(F_CF) != 0;
+ } else
+ cf = (d >> (cnt - 1)) & 0x1;
+ mask = (1 << (16 - cnt)) - 1;
+ res = (d >> cnt) & mask;
+ res |= (d << (17 - cnt));
+ if (ACCESS_FLAG(F_CF)) {
+ res |= 1 << (16 - cnt);
+ }
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
+ F_OF);
+ }
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the RCR instruction and side effects.
+****************************************************************************/
+u32 rcr_long(u32 d, u8 s)
+{
+ u32 res, cnt;
+ u32 mask, cf, ocf = 0;
+
+ /* rotate right through carry */
+ res = d;
+ if ((cnt = s % 33) != 0) {
+ if (cnt == 1) {
+ cf = d & 0x1;
+ ocf = ACCESS_FLAG(F_CF) != 0;
+ } else
+ cf = (d >> (cnt - 1)) & 0x1;
+ mask = (1 << (32 - cnt)) - 1;
+ res = (d >> cnt) & mask;
+ if (cnt != 1)
+ res |= (d << (33 - cnt));
+ if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
+ res |= 1 << (32 - cnt);
+ }
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
+ F_OF);
+ }
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROL instruction and side effects.
+****************************************************************************/
+u8 rol_byte(u8 d, u8 s)
+{
+ register unsigned int res, cnt, mask;
+
+ /* rotate left */
+ /*
+ s is the rotate distance. It varies from 0 - 8.
+ d is the byte object rotated.
+
+ have
+
+ CF B_7 ... B_0
+
+ The new rotate is done mod 8.
+ Much simpler than the "rcl" or "rcr" operations.
+
+ IF n > 0
+ 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0)
+ 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n)
+ */
+ res = d;
+ if ((cnt = s % 8) != 0) {
+ /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
+ res = (d << cnt);
+
+ /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
+ mask = (1 << cnt) - 1;
+ res |= (d >> (8 - cnt)) & mask;
+
+ /* set the new carry flag, Note that it is the low order
+ bit of the result!!! */
+ CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+ /* OVERFLOW is set *IFF* s==1, then it is the
+ xor of CF and the most significant bit. Blecck. */
+ CONDITIONAL_SET_FLAG(s == 1 &&
+ XOR2((res & 0x1) + ((res >> 6) & 0x2)),
+ F_OF);
+ } if (s != 0) {
+ /* set the new carry flag, Note that it is the low order
+ bit of the result!!! */
+ CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+ }
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROL instruction and side effects.
+****************************************************************************/
+u16 rol_word(u16 d, u8 s)
+{
+ register unsigned int res, cnt, mask;
+
+ res = d;
+ if ((cnt = s % 16) != 0) {
+ res = (d << cnt);
+ mask = (1 << cnt) - 1;
+ res |= (d >> (16 - cnt)) & mask;
+ CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+ CONDITIONAL_SET_FLAG(s == 1 &&
+ XOR2((res & 0x1) + ((res >> 14) & 0x2)),
+ F_OF);
+ } if (s != 0) {
+ /* set the new carry flag, Note that it is the low order
+ bit of the result!!! */
+ CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROL instruction and side effects.
+****************************************************************************/
+u32 rol_long(u32 d, u8 s)
+{
+ register u32 res, cnt, mask;
+
+ res = d;
+ if ((cnt = s % 32) != 0) {
+ res = (d << cnt);
+ mask = (1 << cnt) - 1;
+ res |= (d >> (32 - cnt)) & mask;
+ CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+ CONDITIONAL_SET_FLAG(s == 1 &&
+ XOR2((res & 0x1) + ((res >> 30) & 0x2)),
+ F_OF);
+ } if (s != 0) {
+ /* set the new carry flag, Note that it is the low order
+ bit of the result!!! */
+ CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROR instruction and side effects.
+****************************************************************************/
+u8 ror_byte(u8 d, u8 s)
+{
+ register unsigned int res, cnt, mask;
+
+ /* rotate right */
+ /*
+ s is the rotate distance. It varies from 0 - 8.
+ d is the byte object rotated.
+
+ have
+
+ B_7 ... B_0
+
+ The rotate is done mod 8.
+
+ IF n > 0
+ 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
+ 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0)
+ */
+ res = d;
+ if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */
+ /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
+ res = (d << (8 - cnt));
+
+ /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
+ mask = (1 << (8 - cnt)) - 1;
+ res |= (d >> (cnt)) & mask;
+
+ /* set the new carry flag, Note that it is the low order
+ bit of the result!!! */
+ CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
+ /* OVERFLOW is set *IFF* s==1, then it is the
+ xor of the two most significant bits. Blecck. */
+ CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
+ } else if (s != 0) {
+ /* set the new carry flag, Note that it is the low order
+ bit of the result!!! */
+ CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
+ }
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROR instruction and side effects.
+****************************************************************************/
+u16 ror_word(u16 d, u8 s)
+{
+ register unsigned int res, cnt, mask;
+
+ res = d;
+ if ((cnt = s % 16) != 0) {
+ res = (d << (16 - cnt));
+ mask = (1 << (16 - cnt)) - 1;
+ res |= (d >> (cnt)) & mask;
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
+ CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
+ } else if (s != 0) {
+ /* set the new carry flag, Note that it is the low order
+ bit of the result!!! */
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the ROR instruction and side effects.
+****************************************************************************/
+u32 ror_long(u32 d, u8 s)
+{
+ register u32 res, cnt, mask;
+
+ res = d;
+ if ((cnt = s % 32) != 0) {
+ res = (d << (32 - cnt));
+ mask = (1 << (32 - cnt)) - 1;
+ res |= (d >> (cnt)) & mask;
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
+ CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
+ } else if (s != 0) {
+ /* set the new carry flag, Note that it is the low order
+ bit of the result!!! */
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHL instruction and side effects.
+****************************************************************************/
+u8 shl_byte(u8 d, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 8) {
+ cnt = s % 8;
+
+ /* last bit shifted out goes into carry flag */
+ if (cnt > 0) {
+ res = d << cnt;
+ cf = d & (1 << (8 - cnt));
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ } else {
+ res = (u8) d;
+ }
+
+ if (cnt == 1) {
+ /* Needs simplification. */
+ CONDITIONAL_SET_FLAG(
+ (((res & 0x80) == 0x80) ^
+ (ACCESS_FLAG(F_CF) != 0)),
+ /* was (M.x86.R_FLG&F_CF)==F_CF)), */
+ F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ SET_FLAG(F_ZF);
+ }
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHL instruction and side effects.
+****************************************************************************/
+u16 shl_word(u16 d, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 16) {
+ cnt = s % 16;
+ if (cnt > 0) {
+ res = d << cnt;
+ cf = d & (1 << (16 - cnt));
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ } else {
+ res = (u16) d;
+ }
+
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(
+ (((res & 0x8000) == 0x8000) ^
+ (ACCESS_FLAG(F_CF) != 0)),
+ F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ SET_FLAG(F_ZF);
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHL instruction and side effects.
+****************************************************************************/
+u32 shl_long(u32 d, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 32) {
+ cnt = s % 32;
+ if (cnt > 0) {
+ res = d << cnt;
+ cf = d & (1 << (32 - cnt));
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ } else {
+ res = d;
+ }
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
+ (ACCESS_FLAG(F_CF) != 0)), F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ SET_FLAG(F_ZF);
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHR instruction and side effects.
+****************************************************************************/
+u8 shr_byte(u8 d, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 8) {
+ cnt = s % 8;
+ if (cnt > 0) {
+ cf = d & (1 << (cnt - 1));
+ res = d >> cnt;
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ } else {
+ res = (u8) d;
+ }
+
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ SET_FLAG(F_ZF);
+ }
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHR instruction and side effects.
+****************************************************************************/
+u16 shr_word(u16 d, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 16) {
+ cnt = s % 16;
+ if (cnt > 0) {
+ cf = d & (1 << (cnt - 1));
+ res = d >> cnt;
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ } else {
+ res = d;
+ }
+
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ SET_FLAG(F_ZF);
+ CLEAR_FLAG(F_SF);
+ CLEAR_FLAG(F_PF);
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHR instruction and side effects.
+****************************************************************************/
+u32 shr_long(u32 d, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 32) {
+ cnt = s % 32;
+ if (cnt > 0) {
+ cf = d & (1 << (cnt - 1));
+ res = d >> cnt;
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ } else {
+ res = d;
+ }
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ SET_FLAG(F_ZF);
+ CLEAR_FLAG(F_SF);
+ CLEAR_FLAG(F_PF);
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SAR instruction and side effects.
+****************************************************************************/
+u8 sar_byte(u8 d, u8 s)
+{
+ unsigned int cnt, res, cf, mask, sf;
+
+ res = d;
+ sf = d & 0x80;
+ cnt = s % 8;
+ if (cnt > 0 && cnt < 8) {
+ mask = (1 << (8 - cnt)) - 1;
+ cf = d & (1 << (cnt - 1));
+ res = (d >> cnt) & mask;
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ if (sf) {
+ res |= ~mask;
+ }
+ CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+ } else if (cnt >= 8) {
+ if (sf) {
+ res = 0xff;
+ SET_FLAG(F_CF);
+ CLEAR_FLAG(F_ZF);
+ SET_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ } else {
+ res = 0;
+ CLEAR_FLAG(F_CF);
+ SET_FLAG(F_ZF);
+ CLEAR_FLAG(F_SF);
+ CLEAR_FLAG(F_PF);
+ }
+ }
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SAR instruction and side effects.
+****************************************************************************/
+u16 sar_word(u16 d, u8 s)
+{
+ unsigned int cnt, res, cf, mask, sf;
+
+ sf = d & 0x8000;
+ cnt = s % 16;
+ res = d;
+ if (cnt > 0 && cnt < 16) {
+ mask = (1 << (16 - cnt)) - 1;
+ cf = d & (1 << (cnt - 1));
+ res = (d >> cnt) & mask;
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ if (sf) {
+ res |= ~mask;
+ }
+ CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ } else if (cnt >= 16) {
+ if (sf) {
+ res = 0xffff;
+ SET_FLAG(F_CF);
+ CLEAR_FLAG(F_ZF);
+ SET_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ } else {
+ res = 0;
+ CLEAR_FLAG(F_CF);
+ SET_FLAG(F_ZF);
+ CLEAR_FLAG(F_SF);
+ CLEAR_FLAG(F_PF);
+ }
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SAR instruction and side effects.
+****************************************************************************/
+u32 sar_long(u32 d, u8 s)
+{
+ u32 cnt, res, cf, mask, sf;
+
+ sf = d & 0x80000000;
+ cnt = s % 32;
+ res = d;
+ if (cnt > 0 && cnt < 32) {
+ mask = (1 << (32 - cnt)) - 1;
+ cf = d & (1 << (cnt - 1));
+ res = (d >> cnt) & mask;
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ if (sf) {
+ res |= ~mask;
+ }
+ CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ } else if (cnt >= 32) {
+ if (sf) {
+ res = 0xffffffff;
+ SET_FLAG(F_CF);
+ CLEAR_FLAG(F_ZF);
+ SET_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ } else {
+ res = 0;
+ CLEAR_FLAG(F_CF);
+ SET_FLAG(F_ZF);
+ CLEAR_FLAG(F_SF);
+ CLEAR_FLAG(F_PF);
+ }
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHLD instruction and side effects.
+****************************************************************************/
+u16 shld_word (u16 d, u16 fill, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 16) {
+ cnt = s % 16;
+ if (cnt > 0) {
+ res = (d << cnt) | (fill >> (16-cnt));
+ cf = d & (1 << (16 - cnt));
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ } else {
+ res = d;
+ }
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
+ (ACCESS_FLAG(F_CF) != 0)), F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ SET_FLAG(F_ZF);
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHLD instruction and side effects.
+****************************************************************************/
+u32 shld_long (u32 d, u32 fill, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 32) {
+ cnt = s % 32;
+ if (cnt > 0) {
+ res = (d << cnt) | (fill >> (32-cnt));
+ cf = d & (1 << (32 - cnt));
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ } else {
+ res = d;
+ }
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
+ (ACCESS_FLAG(F_CF) != 0)), F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
+ CLEAR_FLAG(F_OF);
+ CLEAR_FLAG(F_SF);
+ SET_FLAG(F_PF);
+ SET_FLAG(F_ZF);
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHRD instruction and side effects.
+****************************************************************************/
+u16 shrd_word (u16 d, u16 fill, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 16) {
+ cnt = s % 16;
+ if (cnt > 0) {
+ cf = d & (1 << (cnt - 1));
+ res = (d >> cnt) | (fill << (16 - cnt));
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ } else {
+ res = d;
+ }
+
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ SET_FLAG(F_ZF);
+ CLEAR_FLAG(F_SF);
+ CLEAR_FLAG(F_PF);
+ }
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SHRD instruction and side effects.
+****************************************************************************/
+u32 shrd_long (u32 d, u32 fill, u8 s)
+{
+ unsigned int cnt, res, cf;
+
+ if (s < 32) {
+ cnt = s % 32;
+ if (cnt > 0) {
+ cf = d & (1 << (cnt - 1));
+ res = (d >> cnt) | (fill << (32 - cnt));
+ CONDITIONAL_SET_FLAG(cf, F_CF);
+ CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ } else {
+ res = d;
+ }
+ if (cnt == 1) {
+ CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
+ } else {
+ CLEAR_FLAG(F_OF);
+ }
+ } else {
+ res = 0;
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ SET_FLAG(F_ZF);
+ CLEAR_FLAG(F_SF);
+ CLEAR_FLAG(F_PF);
+ }
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SBB instruction and side effects.
+****************************************************************************/
+u8 sbb_byte(u8 d, u8 s)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 bc;
+
+ if (ACCESS_FLAG(F_CF))
+ res = d - s - 1;
+ else
+ res = d - s;
+ CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the borrow chain. See note at top */
+ bc = (res & (~d | s)) | (~d & s);
+ CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SBB instruction and side effects.
+****************************************************************************/
+u16 sbb_word(u16 d, u16 s)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 bc;
+
+ if (ACCESS_FLAG(F_CF))
+ res = d - s - 1;
+ else
+ res = d - s;
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the borrow chain. See note at top */
+ bc = (res & (~d | s)) | (~d & s);
+ CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SBB instruction and side effects.
+****************************************************************************/
+u32 sbb_long(u32 d, u32 s)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 bc;
+
+ if (ACCESS_FLAG(F_CF))
+ res = d - s - 1;
+ else
+ res = d - s;
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the borrow chain. See note at top */
+ bc = (res & (~d | s)) | (~d & s);
+ CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SUB instruction and side effects.
+****************************************************************************/
+u8 sub_byte(u8 d, u8 s)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 bc;
+
+ res = d - s;
+ CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the borrow chain. See note at top */
+ bc = (res & (~d | s)) | (~d & s);
+ CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return (u8)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SUB instruction and side effects.
+****************************************************************************/
+u16 sub_word(u16 d, u16 s)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 bc;
+
+ res = d - s;
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the borrow chain. See note at top */
+ bc = (res & (~d | s)) | (~d & s);
+ CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return (u16)res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the SUB instruction and side effects.
+****************************************************************************/
+u32 sub_long(u32 d, u32 s)
+{
+ register u32 res; /* all operands in native machine order */
+ register u32 bc;
+
+ res = d - s;
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+
+ /* calculate the borrow chain. See note at top */
+ bc = (res & (~d | s)) | (~d & s);
+ CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
+ CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
+ CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the TEST instruction and side effects.
+****************************************************************************/
+void test_byte(u8 d, u8 s)
+{
+ register u32 res; /* all operands in native machine order */
+
+ res = d & s;
+
+ CLEAR_FLAG(F_OF);
+ CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ /* AF == dont care */
+ CLEAR_FLAG(F_CF);
+}
+
+/****************************************************************************
+REMARKS:
+Implements the TEST instruction and side effects.
+****************************************************************************/
+void test_word(u16 d, u16 s)
+{
+ register u32 res; /* all operands in native machine order */
+
+ res = d & s;
+
+ CLEAR_FLAG(F_OF);
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ /* AF == dont care */
+ CLEAR_FLAG(F_CF);
+}
+
+/****************************************************************************
+REMARKS:
+Implements the TEST instruction and side effects.
+****************************************************************************/
+void test_long(u32 d, u32 s)
+{
+ register u32 res; /* all operands in native machine order */
+
+ res = d & s;
+
+ CLEAR_FLAG(F_OF);
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ /* AF == dont care */
+ CLEAR_FLAG(F_CF);
+}
+
+/****************************************************************************
+REMARKS:
+Implements the XOR instruction and side effects.
+****************************************************************************/
+u8 xor_byte(u8 d, u8 s)
+{
+ register u8 res; /* all operands in native machine order */
+
+ res = d ^ s;
+ CLEAR_FLAG(F_OF);
+ CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
+ CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the XOR instruction and side effects.
+****************************************************************************/
+u16 xor_word(u16 d, u16 s)
+{
+ register u16 res; /* all operands in native machine order */
+
+ res = d ^ s;
+ CLEAR_FLAG(F_OF);
+ CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
+ CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the XOR instruction and side effects.
+****************************************************************************/
+u32 xor_long(u32 d, u32 s)
+{
+ register u32 res; /* all operands in native machine order */
+
+ res = d ^ s;
+ CLEAR_FLAG(F_OF);
+ CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
+ CONDITIONAL_SET_FLAG(res == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IMUL instruction and side effects.
+****************************************************************************/
+void imul_byte(u8 s)
+{
+ s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
+
+ M.x86.R_AX = res;
+ if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
+ ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IMUL instruction and side effects.
+****************************************************************************/
+void imul_word(u16 s)
+{
+ s32 res = (s16)M.x86.R_AX * (s16)s;
+
+ M.x86.R_AX = (u16)res;
+ M.x86.R_DX = (u16)(res >> 16);
+ if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x00) ||
+ ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFF)) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IMUL instruction and side effects.
+****************************************************************************/
+void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
+{
+#ifdef __HAS_LONG_LONG__
+ s64 res = (s32)d * (s32)s;
+
+ *res_lo = (u32)res;
+ *res_hi = (u32)(res >> 32);
+#else
+ u32 d_lo,d_hi,d_sign;
+ u32 s_lo,s_hi,s_sign;
+ u32 rlo_lo,rlo_hi,rhi_lo;
+
+ if ((d_sign = d & 0x80000000) != 0)
+ d = -d;
+ d_lo = d & 0xFFFF;
+ d_hi = d >> 16;
+ if ((s_sign = s & 0x80000000) != 0)
+ s = -s;
+ s_lo = s & 0xFFFF;
+ s_hi = s >> 16;
+ rlo_lo = d_lo * s_lo;
+ rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
+ rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
+ *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
+ *res_hi = rhi_lo;
+ if (d_sign != s_sign) {
+ d = ~*res_lo;
+ s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
+ *res_lo = ~*res_lo+1;
+ *res_hi = ~*res_hi+(s >> 16);
+ }
+#endif
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IMUL instruction and side effects.
+****************************************************************************/
+void imul_long(u32 s)
+{
+ imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
+ if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00) ||
+ ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFF)) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the MUL instruction and side effects.
+****************************************************************************/
+void mul_byte(u8 s)
+{
+ u16 res = (u16)(M.x86.R_AL * s);
+
+ M.x86.R_AX = res;
+ if (M.x86.R_AH == 0) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the MUL instruction and side effects.
+****************************************************************************/
+void mul_word(u16 s)
+{
+ u32 res = M.x86.R_AX * s;
+
+ M.x86.R_AX = (u16)res;
+ M.x86.R_DX = (u16)(res >> 16);
+ if (M.x86.R_DX == 0) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the MUL instruction and side effects.
+****************************************************************************/
+void mul_long(u32 s)
+{
+#ifdef __HAS_LONG_LONG__
+ u64 res = (u32)M.x86.R_EAX * (u32)s;
+
+ M.x86.R_EAX = (u32)res;
+ M.x86.R_EDX = (u32)(res >> 32);
+#else
+ u32 a,a_lo,a_hi;
+ u32 s_lo,s_hi;
+ u32 rlo_lo,rlo_hi,rhi_lo;
+
+ a = M.x86.R_EAX;
+ a_lo = a & 0xFFFF;
+ a_hi = a >> 16;
+ s_lo = s & 0xFFFF;
+ s_hi = s >> 16;
+ rlo_lo = a_lo * s_lo;
+ rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
+ rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
+ M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
+ M.x86.R_EDX = rhi_lo;
+#endif
+
+ if (M.x86.R_EDX == 0) {
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_OF);
+ } else {
+ SET_FLAG(F_CF);
+ SET_FLAG(F_OF);
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IDIV instruction and side effects.
+****************************************************************************/
+#define abs(a) (((a) < 0) ? -(a) : (a))
+void idiv_byte(u8 s)
+{
+ s32 dvd, div, mod;
+
+ dvd = (s16)M.x86.R_AX;
+ if (s == 0) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ div = dvd / (s8)s;
+ mod = dvd % (s8)s;
+ if (abs(div) > 0x7f) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ M.x86.R_AL = (s8) div;
+ M.x86.R_AH = (s8) mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IDIV instruction and side effects.
+****************************************************************************/
+void idiv_word(u16 s)
+{
+ s32 dvd, div, mod;
+
+ dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
+ if (s == 0) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ div = dvd / (s16)s;
+ mod = dvd % (s16)s;
+ if (abs(div) > 0x7fff) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_SF);
+ CONDITIONAL_SET_FLAG(div == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
+
+ M.x86.R_AX = (u16)div;
+ M.x86.R_DX = (u16)mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the IDIV instruction and side effects.
+****************************************************************************/
+void idiv_long(u32 s)
+{
+#ifdef __HAS_LONG_LONG__
+ s64 dvd, div, mod;
+
+ dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
+ if (s == 0) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ div = dvd / (s32)s;
+ mod = dvd % (s32)s;
+ if (abs(div) > 0x7fffffff) {
+ x86emu_intr_raise(0);
+ return;
+ }
+#else
+ s32 div = 0, mod;
+ s32 h_dvd = M.x86.R_EDX;
+ u32 l_dvd = M.x86.R_EAX;
+ u32 abs_s = s & 0x7FFFFFFF;
+ u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
+ u32 h_s = abs_s >> 1;
+ u32 l_s = abs_s << 31;
+ int counter = 31;
+ int carry;
+
+ if (s == 0) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ do {
+ div <<= 1;
+ carry = (l_dvd >= l_s) ? 0 : 1;
+
+ if (abs_h_dvd < (h_s + carry)) {
+ h_s >>= 1;
+ l_s = abs_s << (--counter);
+ continue;
+ } else {
+ abs_h_dvd -= (h_s + carry);
+ l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
+ : (l_dvd - l_s);
+ h_s >>= 1;
+ l_s = abs_s << (--counter);
+ div |= 1;
+ continue;
+ }
+
+ } while (counter > -1);
+ /* overflow */
+ if (abs_h_dvd || (l_dvd > abs_s)) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ /* sign */
+ div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
+ mod = l_dvd;
+
+#endif
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ CLEAR_FLAG(F_SF);
+ SET_FLAG(F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
+
+ M.x86.R_EAX = (u32)div;
+ M.x86.R_EDX = (u32)mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DIV instruction and side effects.
+****************************************************************************/
+void div_byte(u8 s)
+{
+ u32 dvd, div, mod;
+
+ dvd = M.x86.R_AX;
+ if (s == 0) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ div = dvd / (u8)s;
+ mod = dvd % (u8)s;
+ if (abs(div) > 0xff) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ M.x86.R_AL = (u8)div;
+ M.x86.R_AH = (u8)mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DIV instruction and side effects.
+****************************************************************************/
+void div_word(u16 s)
+{
+ u32 dvd, div, mod;
+
+ dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
+ if (s == 0) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ div = dvd / (u16)s;
+ mod = dvd % (u16)s;
+ if (abs(div) > 0xffff) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_SF);
+ CONDITIONAL_SET_FLAG(div == 0, F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
+
+ M.x86.R_AX = (u16)div;
+ M.x86.R_DX = (u16)mod;
+}
+
+/****************************************************************************
+REMARKS:
+Implements the DIV instruction and side effects.
+****************************************************************************/
+void div_long(u32 s)
+{
+#ifdef __HAS_LONG_LONG__
+ u64 dvd, div, mod;
+
+ dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
+ if (s == 0) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ div = dvd / (u32)s;
+ mod = dvd % (u32)s;
+ if (abs(div) > 0xffffffff) {
+ x86emu_intr_raise(0);
+ return;
+ }
+#else
+ s32 div = 0, mod;
+ s32 h_dvd = M.x86.R_EDX;
+ u32 l_dvd = M.x86.R_EAX;
+
+ u32 h_s = s;
+ u32 l_s = 0;
+ int counter = 32;
+ int carry;
+
+ if (s == 0) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ do {
+ div <<= 1;
+ carry = (l_dvd >= l_s) ? 0 : 1;
+
+ if (h_dvd < (h_s + carry)) {
+ h_s >>= 1;
+ l_s = s << (--counter);
+ continue;
+ } else {
+ h_dvd -= (h_s + carry);
+ l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
+ : (l_dvd - l_s);
+ h_s >>= 1;
+ l_s = s << (--counter);
+ div |= 1;
+ continue;
+ }
+
+ } while (counter > -1);
+ /* overflow */
+ if (h_dvd || (l_dvd > s)) {
+ x86emu_intr_raise(0);
+ return;
+ }
+ mod = l_dvd;
+#endif
+ CLEAR_FLAG(F_CF);
+ CLEAR_FLAG(F_AF);
+ CLEAR_FLAG(F_SF);
+ SET_FLAG(F_ZF);
+ CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
+
+ M.x86.R_EAX = (u32)div;
+ M.x86.R_EDX = (u32)mod;
+}
+
+#endif /* __HAVE_INLINE_ASSEMBLER__ */
+
+/****************************************************************************
+REMARKS:
+Implements the IN string instruction and side effects.
+****************************************************************************/
+void ins(int size)
+{
+ int inc = size;
+
+ if (ACCESS_FLAG(F_DF)) {
+ inc = -size;
+ }
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* in until CX is ZERO. */
+ u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
+ M.x86.R_ECX : M.x86.R_CX);
+ switch (size) {
+ case 1:
+ while (count--) {
+ store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
+ (*sys_inb)(M.x86.R_DX));
+ M.x86.R_DI += inc;
+ }
+ break;
+
+ case 2:
+ while (count--) {
+ store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
+ (*sys_inw)(M.x86.R_DX));
+ M.x86.R_DI += inc;
+ }
+ break;
+ case 4:
+ while (count--) {
+ store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
+ (*sys_inl)(M.x86.R_DX));
+ M.x86.R_DI += inc;
+ break;
+ }
+ }
+ M.x86.R_CX = 0;
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ECX = 0;
+ }
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ } else {
+ switch (size) {
+ case 1:
+ store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
+ (*sys_inb)(M.x86.R_DX));
+ break;
+ case 2:
+ store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
+ (*sys_inw)(M.x86.R_DX));
+ break;
+ case 4:
+ store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
+ (*sys_inl)(M.x86.R_DX));
+ break;
+ }
+ M.x86.R_DI += inc;
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Implements the OUT string instruction and side effects.
+****************************************************************************/
+void outs(int size)
+{
+ int inc = size;
+
+ if (ACCESS_FLAG(F_DF)) {
+ inc = -size;
+ }
+ if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
+ /* dont care whether REPE or REPNE */
+ /* out until CX is ZERO. */
+ u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
+ M.x86.R_ECX : M.x86.R_CX);
+ switch (size) {
+ case 1:
+ while (count--) {
+ (*sys_outb)(M.x86.R_DX,
+ fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
+ M.x86.R_SI += inc;
+ }
+ break;
+
+ case 2:
+ while (count--) {
+ (*sys_outw)(M.x86.R_DX,
+ fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
+ M.x86.R_SI += inc;
+ }
+ break;
+ case 4:
+ while (count--) {
+ (*sys_outl)(M.x86.R_DX,
+ fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
+ M.x86.R_SI += inc;
+ break;
+ }
+ }
+ M.x86.R_CX = 0;
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ M.x86.R_ECX = 0;
+ }
+ M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
+ } else {
+ switch (size) {
+ case 1:
+ (*sys_outb)(M.x86.R_DX,
+ fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
+ break;
+ case 2:
+ (*sys_outw)(M.x86.R_DX,
+ fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
+ break;
+ case 4:
+ (*sys_outl)(M.x86.R_DX,
+ fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
+ break;
+ }
+ M.x86.R_SI += inc;
+ }
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Address to fetch word from
+
+REMARKS:
+Fetches a word from emulator memory using an absolute address.
+****************************************************************************/
+u16 mem_access_word(int addr)
+{
+DB( if (CHECK_MEM_ACCESS())
+ x86emu_check_mem_access(addr);)
+ return (*sys_rdw)(addr);
+}
+
+/****************************************************************************
+REMARKS:
+Pushes a word onto the stack.
+
+NOTE: Do not inline this, as (*sys_wrX) is already inline!
+****************************************************************************/
+void push_word(u16 w)
+{
+DB( if (CHECK_SP_ACCESS())
+ x86emu_check_sp_access();)
+ M.x86.R_SP -= 2;
+ (*sys_wrw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
+}
+
+/****************************************************************************
+REMARKS:
+Pushes a long onto the stack.
+
+NOTE: Do not inline this, as (*sys_wrX) is already inline!
+****************************************************************************/
+void push_long(u32 w)
+{
+DB( if (CHECK_SP_ACCESS())
+ x86emu_check_sp_access();)
+ M.x86.R_SP -= 4;
+ (*sys_wrl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
+}
+
+/****************************************************************************
+REMARKS:
+Pops a word from the stack.
+
+NOTE: Do not inline this, as (*sys_rdX) is already inline!
+****************************************************************************/
+u16 pop_word(void)
+{
+ register u16 res;
+
+DB( if (CHECK_SP_ACCESS())
+ x86emu_check_sp_access();)
+ res = (*sys_rdw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
+ M.x86.R_SP += 2;
+ return res;
+}
+
+/****************************************************************************
+REMARKS:
+Pops a long from the stack.
+
+NOTE: Do not inline this, as (*sys_rdX) is already inline!
+****************************************************************************/
+u32 pop_long(void)
+{
+ register u32 res;
+
+DB( if (CHECK_SP_ACCESS())
+ x86emu_check_sp_access();)
+ res = (*sys_rdl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
+ M.x86.R_SP += 4;
+ return res;
+}
+
+#ifdef __HAVE_INLINE_ASSEMBLER__
+
+u16 aaa_word (u16 d)
+{ return aaa_word_asm(&M.x86.R_EFLG,d); }
+
+u16 aas_word (u16 d)
+{ return aas_word_asm(&M.x86.R_EFLG,d); }
+
+u16 aad_word (u16 d)
+{ return aad_word_asm(&M.x86.R_EFLG,d); }
+
+u16 aam_word (u8 d)
+{ return aam_word_asm(&M.x86.R_EFLG,d); }
+
+u8 adc_byte (u8 d, u8 s)
+{ return adc_byte_asm(&M.x86.R_EFLG,d,s); }
+
+u16 adc_word (u16 d, u16 s)
+{ return adc_word_asm(&M.x86.R_EFLG,d,s); }
+
+u32 adc_long (u32 d, u32 s)
+{ return adc_long_asm(&M.x86.R_EFLG,d,s); }
+
+u8 add_byte (u8 d, u8 s)
+{ return add_byte_asm(&M.x86.R_EFLG,d,s); }
+
+u16 add_word (u16 d, u16 s)
+{ return add_word_asm(&M.x86.R_EFLG,d,s); }
+
+u32 add_long (u32 d, u32 s)
+{ return add_long_asm(&M.x86.R_EFLG,d,s); }
+
+u8 and_byte (u8 d, u8 s)
+{ return and_byte_asm(&M.x86.R_EFLG,d,s); }
+
+u16 and_word (u16 d, u16 s)
+{ return and_word_asm(&M.x86.R_EFLG,d,s); }
+
+u32 and_long (u32 d, u32 s)
+{ return and_long_asm(&M.x86.R_EFLG,d,s); }
+
+u8 cmp_byte (u8 d, u8 s)
+{ return cmp_byte_asm(&M.x86.R_EFLG,d,s); }
+
+u16 cmp_word (u16 d, u16 s)
+{ return cmp_word_asm(&M.x86.R_EFLG,d,s); }
+
+u32 cmp_long (u32 d, u32 s)
+{ return cmp_long_asm(&M.x86.R_EFLG,d,s); }
+
+u8 daa_byte (u8 d)
+{ return daa_byte_asm(&M.x86.R_EFLG,d); }
+
+u8 das_byte (u8 d)
+{ return das_byte_asm(&M.x86.R_EFLG,d); }
+
+u8 dec_byte (u8 d)
+{ return dec_byte_asm(&M.x86.R_EFLG,d); }
+
+u16 dec_word (u16 d)
+{ return dec_word_asm(&M.x86.R_EFLG,d); }
+
+u32 dec_long (u32 d)
+{ return dec_long_asm(&M.x86.R_EFLG,d); }
+
+u8 inc_byte (u8 d)
+{ return inc_byte_asm(&M.x86.R_EFLG,d); }
+
+u16 inc_word (u16 d)
+{ return inc_word_asm(&M.x86.R_EFLG,d); }
+
+u32 inc_long (u32 d)
+{ return inc_long_asm(&M.x86.R_EFLG,d); }
+
+u8 or_byte (u8 d, u8 s)
+{ return or_byte_asm(&M.x86.R_EFLG,d,s); }
+
+u16 or_word (u16 d, u16 s)
+{ return or_word_asm(&M.x86.R_EFLG,d,s); }
+
+u32 or_long (u32 d, u32 s)
+{ return or_long_asm(&M.x86.R_EFLG,d,s); }
+
+u8 neg_byte (u8 s)
+{ return neg_byte_asm(&M.x86.R_EFLG,s); }
+
+u16 neg_word (u16 s)
+{ return neg_word_asm(&M.x86.R_EFLG,s); }
+
+u32 neg_long (u32 s)
+{ return neg_long_asm(&M.x86.R_EFLG,s); }
+
+u8 not_byte (u8 s)
+{ return not_byte_asm(&M.x86.R_EFLG,s); }
+
+u16 not_word (u16 s)
+{ return not_word_asm(&M.x86.R_EFLG,s); }
+
+u32 not_long (u32 s)
+{ return not_long_asm(&M.x86.R_EFLG,s); }
+
+u8 rcl_byte (u8 d, u8 s)
+{ return rcl_byte_asm(&M.x86.R_EFLG,d,s); }
+
+u16 rcl_word (u16 d, u8 s)
+{ return rcl_word_asm(&M.x86.R_EFLG,d,s); }
+
+u32 rcl_long (u32 d, u8 s)
+{ return rcl_long_asm(&M.x86.R_EFLG,d,s); }
+
+u8 rcr_byte (u8 d, u8 s)
+{ return rcr_byte_asm(&M.x86.R_EFLG,d,s); }
+
+u16 rcr_word (u16 d, u8 s)
+{ return rcr_word_asm(&M.x86.R_EFLG,d,s); }
+
+u32 rcr_long (u32 d, u8 s)
+{ return rcr_long_asm(&M.x86.R_EFLG,d,s); }
+
+u8 rol_byte (u8 d, u8 s)
+{ return rol_byte_asm(&M.x86.R_EFLG,d,s); }
+
+u16 rol_word (u16 d, u8 s)
+{ return rol_word_asm(&M.x86.R_EFLG,d,s); }
+
+u32 rol_long (u32 d, u8 s)
+{ return rol_long_asm(&M.x86.R_EFLG,d,s); }
+
+u8 ror_byte (u8 d, u8 s)
+{ return ror_byte_asm(&M.x86.R_EFLG,d,s); }
+
+u16 ror_word (u16 d, u8 s)
+{ return ror_word_asm(&M.x86.R_EFLG,d,s); }
+
+u32 ror_long (u32 d, u8 s)
+{ return ror_long_asm(&M.x86.R_EFLG,d,s); }
+
+u8 shl_byte (u8 d, u8 s)
+{ return shl_byte_asm(&M.x86.R_EFLG,d,s); }
+
+u16 shl_word (u16 d, u8 s)
+{ return shl_word_asm(&M.x86.R_EFLG,d,s); }
+
+u32 shl_long (u32 d, u8 s)
+{ return shl_long_asm(&M.x86.R_EFLG,d,s); }
+
+u8 shr_byte (u8 d, u8 s)
+{ return shr_byte_asm(&M.x86.R_EFLG,d,s); }
+
+u16 shr_word (u16 d, u8 s)
+{ return shr_word_asm(&M.x86.R_EFLG,d,s); }
+
+u32 shr_long (u32 d, u8 s)
+{ return shr_long_asm(&M.x86.R_EFLG,d,s); }
+
+u8 sar_byte (u8 d, u8 s)
+{ return sar_byte_asm(&M.x86.R_EFLG,d,s); }
+
+u16 sar_word (u16 d, u8 s)
+{ return sar_word_asm(&M.x86.R_EFLG,d,s); }
+
+u32 sar_long (u32 d, u8 s)
+{ return sar_long_asm(&M.x86.R_EFLG,d,s); }
+
+u16 shld_word (u16 d, u16 fill, u8 s)
+{ return shld_word_asm(&M.x86.R_EFLG,d,fill,s); }
+
+u32 shld_long (u32 d, u32 fill, u8 s)
+{ return shld_long_asm(&M.x86.R_EFLG,d,fill,s); }
+
+u16 shrd_word (u16 d, u16 fill, u8 s)
+{ return shrd_word_asm(&M.x86.R_EFLG,d,fill,s); }
+
+u32 shrd_long (u32 d, u32 fill, u8 s)
+{ return shrd_long_asm(&M.x86.R_EFLG,d,fill,s); }
+
+u8 sbb_byte (u8 d, u8 s)
+{ return sbb_byte_asm(&M.x86.R_EFLG,d,s); }
+
+u16 sbb_word (u16 d, u16 s)
+{ return sbb_word_asm(&M.x86.R_EFLG,d,s); }
+
+u32 sbb_long (u32 d, u32 s)
+{ return sbb_long_asm(&M.x86.R_EFLG,d,s); }
+
+u8 sub_byte (u8 d, u8 s)
+{ return sub_byte_asm(&M.x86.R_EFLG,d,s); }
+
+u16 sub_word (u16 d, u16 s)
+{ return sub_word_asm(&M.x86.R_EFLG,d,s); }
+
+u32 sub_long (u32 d, u32 s)
+{ return sub_long_asm(&M.x86.R_EFLG,d,s); }
+
+void test_byte (u8 d, u8 s)
+{ test_byte_asm(&M.x86.R_EFLG,d,s); }
+
+void test_word (u16 d, u16 s)
+{ test_word_asm(&M.x86.R_EFLG,d,s); }
+
+void test_long (u32 d, u32 s)
+{ test_long_asm(&M.x86.R_EFLG,d,s); }
+
+u8 xor_byte (u8 d, u8 s)
+{ return xor_byte_asm(&M.x86.R_EFLG,d,s); }
+
+u16 xor_word (u16 d, u16 s)
+{ return xor_word_asm(&M.x86.R_EFLG,d,s); }
+
+u32 xor_long (u32 d, u32 s)
+{ return xor_long_asm(&M.x86.R_EFLG,d,s); }
+
+void imul_byte (u8 s)
+{ imul_byte_asm(&M.x86.R_EFLG,&M.x86.R_AX,M.x86.R_AL,s); }
+
+void imul_word (u16 s)
+{ imul_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,s); }
+
+void imul_long (u32 s)
+{ imul_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s); }
+
+void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
+{ imul_long_asm(&M.x86.R_EFLG,res_lo,res_hi,d,s); }
+
+void mul_byte (u8 s)
+{ mul_byte_asm(&M.x86.R_EFLG,&M.x86.R_AX,M.x86.R_AL,s); }
+
+void mul_word (u16 s)
+{ mul_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,s); }
+
+void mul_long (u32 s)
+{ mul_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s); }
+
+void idiv_byte (u8 s)
+{ idiv_byte_asm(&M.x86.R_EFLG,&M.x86.R_AL,&M.x86.R_AH,M.x86.R_AX,s); }
+
+void idiv_word (u16 s)
+{ idiv_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,M.x86.R_DX,s); }
+
+void idiv_long (u32 s)
+{ idiv_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,M.x86.R_EDX,s); }
+
+void div_byte (u8 s)
+{ div_byte_asm(&M.x86.R_EFLG,&M.x86.R_AL,&M.x86.R_AH,M.x86.R_AX,s); }
+
+void div_word (u16 s)
+{ div_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,M.x86.R_DX,s); }
+
+void div_long (u32 s)
+{ div_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,M.x86.R_EDX,s); }
+
+#endif
diff --git a/cfe/cfe/x86emu/sys.c b/cfe/cfe/x86emu/sys.c
new file mode 100644
index 0000000..f80d755
--- /dev/null
+++ b/cfe/cfe/x86emu/sys.c
@@ -0,0 +1,603 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: This file includes subroutines which are related to
+* programmed I/O and memory access. Included in this module
+* are default functions with limited usefulness. For real
+* uses these functions will most likely be overriden by the
+* user library.
+*
+****************************************************************************/
+/* $XFree86: xc/extras/x86emu/src/x86emu/sys.c,v 1.5 2000/08/23 22:10:01 tsi Exp $ */
+
+#include "x86emu.h"
+#include "x86emu/regs.h"
+#include "x86emu/debug.h"
+#include "x86emu/prim_ops.h"
+#ifdef IN_MODULE
+#include "xf86_ansic.h"
+#else
+/*#include <string.h> */
+#define NULL 0
+#endif
+/*------------------------- Global Variables ------------------------------*/
+
+X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */
+X86EMU_intrFuncs _X86EMU_intrTab[256];
+
+/*----------------------------- Implementation ----------------------------*/
+#if defined(__alpha__) || defined(__alpha)
+/* to cope with broken egcs-1.1.2 :-(((( */
+
+/*
+ * inline functions to do unaligned accesses
+ * from linux/include/asm-alpha/unaligned.h
+ */
+
+/*
+ * EGCS 1.1 knows about arbitrary unaligned loads. Define some
+ * packed structures to talk about such things with.
+ */
+
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
+struct __una_u64 { unsigned long x __attribute__((packed)); };
+struct __una_u32 { unsigned int x __attribute__((packed)); };
+struct __una_u16 { unsigned short x __attribute__((packed)); };
+#endif
+
+static __inline__ unsigned long ldq_u(unsigned long * r11)
+{
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
+ const struct __una_u64 *ptr = (const struct __una_u64 *) r11;
+ return ptr->x;
+#else
+ unsigned long r1,r2;
+ __asm__("ldq_u %0,%3\n\t"
+ "ldq_u %1,%4\n\t"
+ "extql %0,%2,%0\n\t"
+ "extqh %1,%2,%1"
+ :"=&r" (r1), "=&r" (r2)
+ :"r" (r11),
+ "m" (*r11),
+ "m" (*(const unsigned long *)(7+(char *) r11)));
+ return r1 | r2;
+#endif
+}
+
+static __inline__ unsigned long ldl_u(unsigned int * r11)
+{
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
+ const struct __una_u32 *ptr = (const struct __una_u32 *) r11;
+ return ptr->x;
+#else
+ unsigned long r1,r2;
+ __asm__("ldq_u %0,%3\n\t"
+ "ldq_u %1,%4\n\t"
+ "extll %0,%2,%0\n\t"
+ "extlh %1,%2,%1"
+ :"=&r" (r1), "=&r" (r2)
+ :"r" (r11),
+ "m" (*r11),
+ "m" (*(const unsigned long *)(3+(char *) r11)));
+ return r1 | r2;
+#endif
+}
+
+static __inline__ unsigned long ldw_u(unsigned short * r11)
+{
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
+ const struct __una_u16 *ptr = (const struct __una_u16 *) r11;
+ return ptr->x;
+#else
+ unsigned long r1,r2;
+ __asm__("ldq_u %0,%3\n\t"
+ "ldq_u %1,%4\n\t"
+ "extwl %0,%2,%0\n\t"
+ "extwh %1,%2,%1"
+ :"=&r" (r1), "=&r" (r2)
+ :"r" (r11),
+ "m" (*r11),
+ "m" (*(const unsigned long *)(1+(char *) r11)));
+ return r1 | r2;
+#endif
+}
+
+/*
+ * Elemental unaligned stores
+ */
+
+static __inline__ void stq_u(unsigned long r5, unsigned long * r11)
+{
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
+ struct __una_u64 *ptr = (struct __una_u64 *) r11;
+ ptr->x = r5;
+#else
+ unsigned long r1,r2,r3,r4;
+
+ __asm__("ldq_u %3,%1\n\t"
+ "ldq_u %2,%0\n\t"
+ "insqh %6,%7,%5\n\t"
+ "insql %6,%7,%4\n\t"
+ "mskqh %3,%7,%3\n\t"
+ "mskql %2,%7,%2\n\t"
+ "bis %3,%5,%3\n\t"
+ "bis %2,%4,%2\n\t"
+ "stq_u %3,%1\n\t"
+ "stq_u %2,%0"
+ :"=m" (*r11),
+ "=m" (*(unsigned long *)(7+(char *) r11)),
+ "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4)
+ :"r" (r5), "r" (r11));
+#endif
+}
+
+static __inline__ void stl_u(unsigned long r5, unsigned int * r11)
+{
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
+ struct __una_u32 *ptr = (struct __una_u32 *) r11;
+ ptr->x = r5;
+#else
+ unsigned long r1,r2,r3,r4;
+
+ __asm__("ldq_u %3,%1\n\t"
+ "ldq_u %2,%0\n\t"
+ "inslh %6,%7,%5\n\t"
+ "insll %6,%7,%4\n\t"
+ "msklh %3,%7,%3\n\t"
+ "mskll %2,%7,%2\n\t"
+ "bis %3,%5,%3\n\t"
+ "bis %2,%4,%2\n\t"
+ "stq_u %3,%1\n\t"
+ "stq_u %2,%0"
+ :"=m" (*r11),
+ "=m" (*(unsigned long *)(3+(char *) r11)),
+ "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4)
+ :"r" (r5), "r" (r11));
+#endif
+}
+
+static __inline__ void stw_u(unsigned long r5, unsigned short * r11)
+{
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
+ struct __una_u16 *ptr = (struct __una_u16 *) r11;
+ ptr->x = r5;
+#else
+ unsigned long r1,r2,r3,r4;
+
+ __asm__("ldq_u %3,%1\n\t"
+ "ldq_u %2,%0\n\t"
+ "inswh %6,%7,%5\n\t"
+ "inswl %6,%7,%4\n\t"
+ "mskwh %3,%7,%3\n\t"
+ "mskwl %2,%7,%2\n\t"
+ "bis %3,%5,%3\n\t"
+ "bis %2,%4,%2\n\t"
+ "stq_u %3,%1\n\t"
+ "stq_u %2,%0"
+ :"=m" (*r11),
+ "=m" (*(unsigned long *)(1+(char *) r11)),
+ "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4)
+ :"r" (r5), "r" (r11));
+#endif
+}
+#endif
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+
+RETURNS:
+Byte value read from emulator memory.
+
+REMARKS:
+Reads a byte value from the emulator memory.
+****************************************************************************/
+u8 X86API rdb(
+ u32 addr)
+{
+ u8 val;
+
+ if (addr > M.mem_size - 1) {
+ DB(printk("mem_read: address %#lx out of range!\n", addr);)
+ HALT_SYS();
+ }
+ val = *(u8*)(M.mem_base + addr);
+DB( if (DEBUG_MEM_TRACE())
+ printk("%#08x 1 -> %#x\n", addr, val);)
+ return val;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+
+RETURNS:
+Word value read from emulator memory.
+
+REMARKS:
+Reads a word value from the emulator memory.
+****************************************************************************/
+u16 X86API rdw(
+ u32 addr)
+{
+ u16 val = 0;
+
+ if (addr > M.mem_size - 2) {
+ DB(printk("mem_read: address %#lx out of range!\n", addr);)
+ HALT_SYS();
+ }
+#ifdef __BIG_ENDIAN__
+ if (addr & 0x1) {
+ val = (*(u8*)(M.mem_base + addr) |
+ (*(u8*)(M.mem_base + addr + 1) << 8));
+ }
+ else
+#endif
+#if defined(__alpha__) || defined(__alpha)
+ val = ldw_u((u16*)(M.mem_base + addr));
+#else
+ val = *(u16*)(M.mem_base + addr);
+#endif
+ DB( if (DEBUG_MEM_TRACE())
+ printk("%#08x 2 -> %#x\n", addr, val);)
+ return val;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+
+RETURNS:
+Long value read from emulator memory.
+REMARKS:
+Reads a long value from the emulator memory.
+****************************************************************************/
+u32 X86API rdl(
+ u32 addr)
+{
+ u32 val = 0;
+
+ if (addr > M.mem_size - 4) {
+ DB(printk("mem_read: address %#lx out of range!\n", addr);)
+ HALT_SYS();
+ }
+#ifdef __BIG_ENDIAN__
+ if (addr & 0x3) {
+ val = (*(u8*)(M.mem_base + addr + 0) |
+ (*(u8*)(M.mem_base + addr + 1) << 8) |
+ (*(u8*)(M.mem_base + addr + 2) << 16) |
+ (*(u8*)(M.mem_base + addr + 3) << 24));
+ }
+ else
+#endif
+#if defined(__alpha__) || defined(__alpha)
+ val = ldl_u((u32*)(M.mem_base + addr));
+#else
+ val = *(u32*)(M.mem_base + addr);
+#endif
+DB( if (DEBUG_MEM_TRACE())
+ printk("%#08x 4 -> %#x\n", addr, val);)
+ return val;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+val - Value to store
+
+REMARKS:
+Writes a byte value to emulator memory.
+****************************************************************************/
+void X86API wrb(
+ u32 addr,
+ u8 val)
+{
+DB( if (DEBUG_MEM_TRACE())
+ printk("%#08x 1 <- %#x\n", addr, val);)
+ if (addr > M.mem_size - 1) {
+ DB(printk("mem_write: address %#lx out of range!\n", addr);)
+ HALT_SYS();
+ }
+ *(u8*)(M.mem_base + addr) = val;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+val - Value to store
+
+REMARKS:
+Writes a word value to emulator memory.
+****************************************************************************/
+void X86API wrw(
+ u32 addr,
+ u16 val)
+{
+DB( if (DEBUG_MEM_TRACE())
+ printk("%#08x 2 <- %#x\n", addr, val);)
+ if (addr > M.mem_size - 2) {
+ DB(printk("mem_write: address %#lx out of range!\n", addr);)
+ HALT_SYS();
+ }
+#ifdef __BIG_ENDIAN__
+ if (addr & 0x1) {
+ *(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff;
+ *(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff;
+ }
+ else
+#endif
+#if defined(__alpha__) || defined(__alpha)
+ stw_u(val,(u16*)(M.mem_base + addr));
+#else
+ *(u16*)(M.mem_base + addr) = val;
+#endif
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - Emulator memory address to read
+val - Value to store
+
+REMARKS:
+Writes a long value to emulator memory.
+****************************************************************************/
+void X86API wrl(
+ u32 addr,
+ u32 val)
+{
+DB( if (DEBUG_MEM_TRACE())
+ printk("%#08x 4 <- %#x\n", addr, val);)
+ if (addr > M.mem_size - 4) {
+ DB(printk("mem_write: address %#lx out of range!\n", addr);)
+ HALT_SYS();
+ }
+#ifdef __BIG_ENDIAN__
+ if (addr & 0x1) {
+ *(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff;
+ *(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff;
+ *(u8*)(M.mem_base + addr + 2) = (val >> 16) & 0xff;
+ *(u8*)(M.mem_base + addr + 3) = (val >> 24) & 0xff;
+ }
+ else
+#endif
+#if defined(__alpha__) || defined(__alpha)
+ stl_u(val,(u32*)(M.mem_base + addr));
+#else
+ *(u32*)(M.mem_base + addr) = val;
+#endif
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - PIO address to read
+RETURN:
+0
+REMARKS:
+Default PIO byte read function. Doesn't perform real inb.
+****************************************************************************/
+static u8 X86API p_inb(
+ X86EMU_pioAddr addr)
+{
+DB( if (DEBUG_IO_TRACE())
+ printk("inb %#04x \n", addr);)
+ return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - PIO address to read
+RETURN:
+0
+REMARKS:
+Default PIO word read function. Doesn't perform real inw.
+****************************************************************************/
+static u16 X86API p_inw(
+ X86EMU_pioAddr addr)
+{
+DB( if (DEBUG_IO_TRACE())
+ printk("inw %#04x \n", addr);)
+ return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - PIO address to read
+RETURN:
+0
+REMARKS:
+Default PIO long read function. Doesn't perform real inl.
+****************************************************************************/
+static u32 X86API p_inl(
+ X86EMU_pioAddr addr)
+{
+DB( if (DEBUG_IO_TRACE())
+ printk("inl %#04x \n", addr);)
+ return 0;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - PIO address to write
+val - Value to store
+REMARKS:
+Default PIO byte write function. Doesn't perform real outb.
+****************************************************************************/
+static void X86API p_outb(
+ X86EMU_pioAddr addr,
+ u8 val)
+{
+DB( if (DEBUG_IO_TRACE())
+ printk("outb %#02x -> %#04x \n", val, addr);)
+ return;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - PIO address to write
+val - Value to store
+REMARKS:
+Default PIO word write function. Doesn't perform real outw.
+****************************************************************************/
+static void X86API p_outw(
+ X86EMU_pioAddr addr,
+ u16 val)
+{
+DB( if (DEBUG_IO_TRACE())
+ printk("outw %#04x -> %#04x \n", val, addr);)
+ return;
+}
+
+/****************************************************************************
+PARAMETERS:
+addr - PIO address to write
+val - Value to store
+REMARKS:
+Default PIO ;ong write function. Doesn't perform real outl.
+****************************************************************************/
+static void X86API p_outl(
+ X86EMU_pioAddr addr,
+ u32 val)
+{
+DB( if (DEBUG_IO_TRACE())
+ printk("outl %#08x -> %#04x \n", val, addr);)
+ return;
+}
+
+/*------------------------- Global Variables ------------------------------*/
+
+u8 (X86APIP sys_rdb)(u32 addr) = rdb;
+u16 (X86APIP sys_rdw)(u32 addr) = rdw;
+u32 (X86APIP sys_rdl)(u32 addr) = rdl;
+void (X86APIP sys_wrb)(u32 addr,u8 val) = wrb;
+void (X86APIP sys_wrw)(u32 addr,u16 val) = wrw;
+void (X86APIP sys_wrl)(u32 addr,u32 val) = wrl;
+u8 (X86APIP sys_inb)(X86EMU_pioAddr addr) = p_inb;
+u16 (X86APIP sys_inw)(X86EMU_pioAddr addr) = p_inw;
+u32 (X86APIP sys_inl)(X86EMU_pioAddr addr) = p_inl;
+void (X86APIP sys_outb)(X86EMU_pioAddr addr, u8 val) = p_outb;
+void (X86APIP sys_outw)(X86EMU_pioAddr addr, u16 val) = p_outw;
+void (X86APIP sys_outl)(X86EMU_pioAddr addr, u32 val) = p_outl;
+
+/*----------------------------- Setup -------------------------------------*/
+
+/****************************************************************************
+PARAMETERS:
+funcs - New memory function pointers to make active
+
+REMARKS:
+This function is used to set the pointers to functions which access
+memory space, allowing the user application to override these functions
+and hook them out as necessary for their application.
+****************************************************************************/
+void X86EMU_setupMemFuncs(
+ X86EMU_memFuncs *funcs)
+{
+ sys_rdb = funcs->rdb;
+ sys_rdw = funcs->rdw;
+ sys_rdl = funcs->rdl;
+ sys_wrb = funcs->wrb;
+ sys_wrw = funcs->wrw;
+ sys_wrl = funcs->wrl;
+}
+
+/****************************************************************************
+PARAMETERS:
+funcs - New programmed I/O function pointers to make active
+
+REMARKS:
+This function is used to set the pointers to functions which access
+I/O space, allowing the user application to override these functions
+and hook them out as necessary for their application.
+****************************************************************************/
+void X86EMU_setupPioFuncs(
+ X86EMU_pioFuncs *funcs)
+{
+ sys_inb = funcs->inb;
+ sys_inw = funcs->inw;
+ sys_inl = funcs->inl;
+ sys_outb = funcs->outb;
+ sys_outw = funcs->outw;
+ sys_outl = funcs->outl;
+}
+
+/****************************************************************************
+PARAMETERS:
+funcs - New interrupt vector table to make active
+
+REMARKS:
+This function is used to set the pointers to functions which handle
+interrupt processing in the emulator, allowing the user application to
+hook interrupts as necessary for their application. Any interrupts that
+are not hooked by the user application, and reflected and handled internally
+in the emulator via the interrupt vector table. This allows the application
+to get control when the code being emulated executes specific software
+interrupts.
+****************************************************************************/
+void X86EMU_setupIntrFuncs(
+ X86EMU_intrFuncs funcs[])
+{
+ int i;
+
+ for (i=0; i < 256; i++)
+ _X86EMU_intrTab[i] = NULL;
+ if (funcs) {
+ for (i = 0; i < 256; i++)
+ _X86EMU_intrTab[i] = funcs[i];
+ }
+}
+
+/****************************************************************************
+PARAMETERS:
+int - New software interrupt to prepare for
+
+REMARKS:
+This function is used to set up the emulator state to exceute a software
+interrupt. This can be used by the user application code to allow an
+interrupt to be hooked, examined and then reflected back to the emulator
+so that the code in the emulator will continue processing the software
+interrupt as per normal. This essentially allows system code to actively
+hook and handle certain software interrupts as necessary.
+****************************************************************************/
+void X86EMU_prepareForInt(
+ int num)
+{
+ push_word((u16)M.x86.R_FLG);
+ CLEAR_FLAG(F_IF);
+ CLEAR_FLAG(F_TF);
+ push_word(M.x86.R_CS);
+ M.x86.R_CS = mem_access_word(num * 4 + 2);
+ push_word(M.x86.R_IP);
+ M.x86.R_IP = mem_access_word(num * 4);
+ M.x86.intr = 0;
+}
diff --git a/cfe/cfe/x86emu/validate.c b/cfe/cfe/x86emu/validate.c
new file mode 100644
index 0000000..239f6c1
--- /dev/null
+++ b/cfe/cfe/x86emu/validate.c
@@ -0,0 +1,765 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: Watcom C 10.6 or later
+* Environment: 32-bit DOS
+* Developer: Kendall Bennett
+*
+* Description: Program to validate the x86 emulator library for
+* correctness. We run the emulator primitive operations
+* functions against the real x86 CPU, and compare the result
+* and flags to ensure correctness.
+*
+* We use inline assembler to compile and build this program.
+*
+****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include "x86emu.h"
+#include "x86emu/prim_asm.h"
+
+/*-------------------------- Implementation -------------------------------*/
+
+#define true 1
+#define false 0
+
+#define ALL_FLAGS (F_CF | F_PF | F_AF | F_ZF | F_SF | F_OF)
+
+#define VAL_START_BINARY(parm_type,res_type,dmax,smax,dincr,sincr) \
+{ \
+ parm_type d,s; \
+ res_type r,r_asm; \
+ ulong flags,inflags; \
+ int f,failed = false; \
+ char buf1[80],buf2[80]; \
+ for (d = 0; d < dmax; d += dincr) { \
+ for (s = 0; s < smax; s += sincr) { \
+ M.x86.R_EFLG = inflags = flags = def_flags; \
+ for (f = 0; f < 2; f++) {
+
+#define VAL_TEST_BINARY(name) \
+ r_asm = name##_asm(&flags,d,s); \
+ r = name(d,s); \
+ if (r != r_asm || M.x86.R_EFLG != flags) \
+ failed = true; \
+ if (failed || trace) {
+
+#define VAL_TEST_BINARY_VOID(name) \
+ name##_asm(&flags,d,s); \
+ name(d,s); \
+ r = r_asm = 0; \
+ if (M.x86.R_EFLG != flags) \
+ failed = true; \
+ if (failed || trace) {
+
+#define VAL_FAIL_BYTE_BYTE_BINARY(name) \
+ if (failed) \
+ printk("fail\n"); \
+ printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \
+ r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
+ printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \
+ r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));
+
+#define VAL_FAIL_WORD_WORD_BINARY(name) \
+ if (failed) \
+ printk("fail\n"); \
+ printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \
+ r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
+ printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \
+ r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));
+
+#define VAL_FAIL_LONG_LONG_BINARY(name) \
+ if (failed) \
+ printk("fail\n"); \
+ printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \
+ r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
+ printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \
+ r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));
+
+#define VAL_END_BINARY() \
+ } \
+ M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (!failed) \
+ printk("passed\n"); \
+}
+
+#define VAL_BYTE_BYTE_BINARY(name) \
+ printk("Validating %s ... ", #name); \
+ VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \
+ VAL_TEST_BINARY(name) \
+ VAL_FAIL_BYTE_BYTE_BINARY(name) \
+ VAL_END_BINARY()
+
+#define VAL_WORD_WORD_BINARY(name) \
+ printk("Validating %s ... ", #name); \
+ VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \
+ VAL_TEST_BINARY(name) \
+ VAL_FAIL_WORD_WORD_BINARY(name) \
+ VAL_END_BINARY()
+
+#define VAL_LONG_LONG_BINARY(name) \
+ printk("Validating %s ... ", #name); \
+ VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \
+ VAL_TEST_BINARY(name) \
+ VAL_FAIL_LONG_LONG_BINARY(name) \
+ VAL_END_BINARY()
+
+#define VAL_VOID_BYTE_BINARY(name) \
+ printk("Validating %s ... ", #name); \
+ VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \
+ VAL_TEST_BINARY_VOID(name) \
+ VAL_FAIL_BYTE_BYTE_BINARY(name) \
+ VAL_END_BINARY()
+
+#define VAL_VOID_WORD_BINARY(name) \
+ printk("Validating %s ... ", #name); \
+ VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \
+ VAL_TEST_BINARY_VOID(name) \
+ VAL_FAIL_WORD_WORD_BINARY(name) \
+ VAL_END_BINARY()
+
+#define VAL_VOID_LONG_BINARY(name) \
+ printk("Validating %s ... ", #name); \
+ VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \
+ VAL_TEST_BINARY_VOID(name) \
+ VAL_FAIL_LONG_LONG_BINARY(name) \
+ VAL_END_BINARY()
+
+#define VAL_BYTE_ROTATE(name) \
+ printk("Validating %s ... ", #name); \
+ VAL_START_BINARY(u8,u8,0xFF,8,1,1) \
+ VAL_TEST_BINARY(name) \
+ VAL_FAIL_BYTE_BYTE_BINARY(name) \
+ VAL_END_BINARY()
+
+#define VAL_WORD_ROTATE(name) \
+ printk("Validating %s ... ", #name); \
+ VAL_START_BINARY(u16,u16,0xFF00,16,0x100,1) \
+ VAL_TEST_BINARY(name) \
+ VAL_FAIL_WORD_WORD_BINARY(name) \
+ VAL_END_BINARY()
+
+#define VAL_LONG_ROTATE(name) \
+ printk("Validating %s ... ", #name); \
+ VAL_START_BINARY(u32,u32,0xFF000000,32,0x1000000,1) \
+ VAL_TEST_BINARY(name) \
+ VAL_FAIL_LONG_LONG_BINARY(name) \
+ VAL_END_BINARY()
+
+#define VAL_START_TERNARY(parm_type,res_type,dmax,smax,dincr,sincr,maxshift)\
+{ \
+ parm_type d,s; \
+ res_type r,r_asm; \
+ u8 shift; \
+ u32 flags,inflags; \
+ int f,failed = false; \
+ char buf1[80],buf2[80]; \
+ for (d = 0; d < dmax; d += dincr) { \
+ for (s = 0; s < smax; s += sincr) { \
+ for (shift = 0; shift < maxshift; shift += 1) { \
+ M.x86.R_EFLG = inflags = flags = def_flags; \
+ for (f = 0; f < 2; f++) {
+
+#define VAL_TEST_TERNARY(name) \
+ r_asm = name##_asm(&flags,d,s,shift); \
+ r = name(d,s,shift); \
+ if (r != r_asm || M.x86.R_EFLG != flags) \
+ failed = true; \
+ if (failed || trace) {
+
+#define VAL_FAIL_WORD_WORD_TERNARY(name) \
+ if (failed) \
+ printk("fail\n"); \
+ printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \
+ r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
+ printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \
+ r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags));
+
+#define VAL_FAIL_LONG_LONG_TERNARY(name) \
+ if (failed) \
+ printk("fail\n"); \
+ printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \
+ r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
+ printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \
+ r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags));
+
+#define VAL_END_TERNARY() \
+ } \
+ M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (!failed) \
+ printk("passed\n"); \
+}
+
+#define VAL_WORD_ROTATE_DBL(name) \
+ printk("Validating %s ... ", #name); \
+ VAL_START_TERNARY(u16,u16,0xFF00,0xFF00,0x100,0x100,16) \
+ VAL_TEST_TERNARY(name) \
+ VAL_FAIL_WORD_WORD_TERNARY(name) \
+ VAL_END_TERNARY()
+
+#define VAL_LONG_ROTATE_DBL(name) \
+ printk("Validating %s ... ", #name); \
+ VAL_START_TERNARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000,32) \
+ VAL_TEST_TERNARY(name) \
+ VAL_FAIL_LONG_LONG_TERNARY(name) \
+ VAL_END_TERNARY()
+
+#define VAL_START_UNARY(parm_type,max,incr) \
+{ \
+ parm_type d,r,r_asm; \
+ u32 flags,inflags; \
+ int f,failed = false; \
+ char buf1[80],buf2[80]; \
+ for (d = 0; d < max; d += incr) { \
+ M.x86.R_EFLG = inflags = flags = def_flags; \
+ for (f = 0; f < 2; f++) {
+
+#define VAL_TEST_UNARY(name) \
+ r_asm = name##_asm(&flags,d); \
+ r = name(d); \
+ if (r != r_asm || M.x86.R_EFLG != flags) { \
+ failed = true;
+
+#define VAL_FAIL_BYTE_UNARY(name) \
+ printk("fail\n"); \
+ printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \
+ r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
+ printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \
+ r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags));
+
+#define VAL_FAIL_WORD_UNARY(name) \
+ printk("fail\n"); \
+ printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \
+ r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
+ printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \
+ r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags));
+
+#define VAL_FAIL_LONG_UNARY(name) \
+ printk("fail\n"); \
+ printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \
+ r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
+ printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \
+ r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags));
+
+#define VAL_END_UNARY() \
+ } \
+ M.x86.R_EFLG = inflags = flags = def_flags | ALL_FLAGS; \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (!failed) \
+ printk("passed\n"); \
+}
+
+#define VAL_BYTE_UNARY(name) \
+ printk("Validating %s ... ", #name); \
+ VAL_START_UNARY(u8,0xFF,0x1) \
+ VAL_TEST_UNARY(name) \
+ VAL_FAIL_BYTE_UNARY(name) \
+ VAL_END_UNARY()
+
+#define VAL_WORD_UNARY(name) \
+ printk("Validating %s ... ", #name); \
+ VAL_START_UNARY(u16,0xFF00,0x100) \
+ VAL_TEST_UNARY(name) \
+ VAL_FAIL_WORD_UNARY(name) \
+ VAL_END_UNARY()
+
+#define VAL_WORD_BYTE_UNARY(name) \
+ printk("Validating %s ... ", #name); \
+ VAL_START_UNARY(u16,0xFF,0x1) \
+ VAL_TEST_UNARY(name) \
+ VAL_FAIL_WORD_UNARY(name) \
+ VAL_END_UNARY()
+
+#define VAL_LONG_UNARY(name) \
+ printk("Validating %s ... ", #name); \
+ VAL_START_UNARY(u32,0xFF000000,0x1000000) \
+ VAL_TEST_UNARY(name) \
+ VAL_FAIL_LONG_UNARY(name) \
+ VAL_END_UNARY()
+
+#define VAL_BYTE_MUL(name) \
+ printk("Validating %s ... ", #name); \
+{ \
+ u8 d,s; \
+ u16 r,r_asm; \
+ u32 flags,inflags; \
+ int f,failed = false; \
+ char buf1[80],buf2[80]; \
+ for (d = 0; d < 0xFF; d += 1) { \
+ for (s = 0; s < 0xFF; s += 1) { \
+ M.x86.R_EFLG = inflags = flags = def_flags; \
+ for (f = 0; f < 2; f++) { \
+ name##_asm(&flags,&r_asm,d,s); \
+ M.x86.R_AL = d; \
+ name(s); \
+ r = M.x86.R_AX; \
+ if (r != r_asm || M.x86.R_EFLG != flags) \
+ failed = true; \
+ if (failed || trace) { \
+ if (failed) \
+ printk("fail\n"); \
+ printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \
+ r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
+ printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \
+ r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
+ } \
+ M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (!failed) \
+ printk("passed\n"); \
+}
+
+#define VAL_WORD_MUL(name) \
+ printk("Validating %s ... ", #name); \
+{ \
+ u16 d,s; \
+ u16 r_lo,r_asm_lo; \
+ u16 r_hi,r_asm_hi; \
+ u32 flags,inflags; \
+ int f,failed = false; \
+ char buf1[80],buf2[80]; \
+ for (d = 0; d < 0xFF00; d += 0x100) { \
+ for (s = 0; s < 0xFF00; s += 0x100) { \
+ M.x86.R_EFLG = inflags = flags = def_flags; \
+ for (f = 0; f < 2; f++) { \
+ name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \
+ M.x86.R_AX = d; \
+ name(s); \
+ r_lo = M.x86.R_AX; \
+ r_hi = M.x86.R_DX; \
+ if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\
+ failed = true; \
+ if (failed || trace) { \
+ if (failed) \
+ printk("fail\n"); \
+ printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \
+ r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
+ printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \
+ r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
+ } \
+ M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (!failed) \
+ printk("passed\n"); \
+}
+
+#define VAL_LONG_MUL(name) \
+ printk("Validating %s ... ", #name); \
+{ \
+ u32 d,s; \
+ u32 r_lo,r_asm_lo; \
+ u32 r_hi,r_asm_hi; \
+ u32 flags,inflags; \
+ int f,failed = false; \
+ char buf1[80],buf2[80]; \
+ for (d = 0; d < 0xFF000000; d += 0x1000000) { \
+ for (s = 0; s < 0xFF000000; s += 0x1000000) { \
+ M.x86.R_EFLG = inflags = flags = def_flags; \
+ for (f = 0; f < 2; f++) { \
+ name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \
+ M.x86.R_EAX = d; \
+ name(s); \
+ r_lo = M.x86.R_EAX; \
+ r_hi = M.x86.R_EDX; \
+ if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\
+ failed = true; \
+ if (failed || trace) { \
+ if (failed) \
+ printk("fail\n"); \
+ printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \
+ r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
+ printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \
+ r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
+ } \
+ M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (!failed) \
+ printk("passed\n"); \
+}
+
+#define VAL_BYTE_DIV(name) \
+ printk("Validating %s ... ", #name); \
+{ \
+ u16 d,s; \
+ u8 r_quot,r_rem,r_asm_quot,r_asm_rem; \
+ u32 flags,inflags; \
+ int f,failed = false; \
+ char buf1[80],buf2[80]; \
+ for (d = 0; d < 0xFF00; d += 0x100) { \
+ for (s = 1; s < 0xFF; s += 1) { \
+ M.x86.R_EFLG = inflags = flags = def_flags; \
+ for (f = 0; f < 2; f++) { \
+ M.x86.intr = 0; \
+ M.x86.R_AX = d; \
+ name(s); \
+ r_quot = M.x86.R_AL; \
+ r_rem = M.x86.R_AH; \
+ if (M.x86.intr & INTR_SYNCH) \
+ continue; \
+ name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,s); \
+ if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \
+ failed = true; \
+ if (failed || trace) { \
+ if (failed) \
+ printk("fail\n"); \
+ printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \
+ r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
+ printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \
+ r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
+ } \
+ M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (!failed) \
+ printk("passed\n"); \
+}
+
+#define VAL_WORD_DIV(name) \
+ printk("Validating %s ... ", #name); \
+{ \
+ u32 d,s; \
+ u16 r_quot,r_rem,r_asm_quot,r_asm_rem; \
+ u32 flags,inflags; \
+ int f,failed = false; \
+ char buf1[80],buf2[80]; \
+ for (d = 0; d < 0xFF000000; d += 0x1000000) { \
+ for (s = 0x100; s < 0xFF00; s += 0x100) { \
+ M.x86.R_EFLG = inflags = flags = def_flags; \
+ for (f = 0; f < 2; f++) { \
+ M.x86.intr = 0; \
+ M.x86.R_AX = d & 0xFFFF; \
+ M.x86.R_DX = d >> 16; \
+ name(s); \
+ r_quot = M.x86.R_AX; \
+ r_rem = M.x86.R_DX; \
+ if (M.x86.intr & INTR_SYNCH) \
+ continue; \
+ name##_asm(&flags,&r_asm_quot,&r_asm_rem,d & 0xFFFF,d >> 16,s);\
+ if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \
+ failed = true; \
+ if (failed || trace) { \
+ if (failed) \
+ printk("fail\n"); \
+ printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \
+ r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
+ printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \
+ r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
+ } \
+ M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (!failed) \
+ printk("passed\n"); \
+}
+
+#define VAL_LONG_DIV(name) \
+ printk("Validating %s ... ", #name); \
+{ \
+ u32 d,s; \
+ u32 r_quot,r_rem,r_asm_quot,r_asm_rem; \
+ u32 flags,inflags; \
+ int f,failed = false; \
+ char buf1[80],buf2[80]; \
+ for (d = 0; d < 0xFF000000; d += 0x1000000) { \
+ for (s = 0x100; s < 0xFF00; s += 0x100) { \
+ M.x86.R_EFLG = inflags = flags = def_flags; \
+ for (f = 0; f < 2; f++) { \
+ M.x86.intr = 0; \
+ M.x86.R_EAX = d; \
+ M.x86.R_EDX = 0; \
+ name(s); \
+ r_quot = M.x86.R_EAX; \
+ r_rem = M.x86.R_EDX; \
+ if (M.x86.intr & INTR_SYNCH) \
+ continue; \
+ name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,0,s); \
+ if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \
+ failed = true; \
+ if (failed || trace) { \
+ if (failed) \
+ printk("fail\n"); \
+ printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \
+ r_quot, r_rem, #name, 0, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
+ printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \
+ r_asm_quot, r_asm_rem, #name"_asm", 0, d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
+ } \
+ M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (failed) \
+ break; \
+ } \
+ if (!failed) \
+ printk("passed\n"); \
+}
+
+void printk(const char *fmt, ...)
+{
+ va_list argptr;
+ va_start(argptr, fmt);
+ vfprintf(stdout, fmt, argptr);
+ fflush(stdout);
+ va_end(argptr);
+}
+
+char * print_flags(char *buf,ulong flags)
+{
+ char *separator = "";
+
+ buf[0] = 0;
+ if (flags & F_CF) {
+ strcat(buf,separator);
+ strcat(buf,"CF");
+ separator = ",";
+ }
+ if (flags & F_PF) {
+ strcat(buf,separator);
+ strcat(buf,"PF");
+ separator = ",";
+ }
+ if (flags & F_AF) {
+ strcat(buf,separator);
+ strcat(buf,"AF");
+ separator = ",";
+ }
+ if (flags & F_ZF) {
+ strcat(buf,separator);
+ strcat(buf,"ZF");
+ separator = ",";
+ }
+ if (flags & F_SF) {
+ strcat(buf,separator);
+ strcat(buf,"SF");
+ separator = ",";
+ }
+ if (flags & F_OF) {
+ strcat(buf,separator);
+ strcat(buf,"OF");
+ separator = ",";
+ }
+ if (separator[0] == 0)
+ strcpy(buf,"None");
+ return buf;
+}
+
+int main(int argc)
+{
+ ulong def_flags;
+ int trace = false;
+
+ if (argc > 1)
+ trace = true;
+ memset(&M, 0, sizeof(M));
+ def_flags = get_flags_asm() & ~ALL_FLAGS;
+
+ VAL_WORD_UNARY(aaa_word);
+ VAL_WORD_UNARY(aas_word);
+
+ VAL_WORD_UNARY(aad_word);
+ VAL_WORD_UNARY(aam_word);
+
+ VAL_BYTE_BYTE_BINARY(adc_byte);
+ VAL_WORD_WORD_BINARY(adc_word);
+ VAL_LONG_LONG_BINARY(adc_long);
+
+ VAL_BYTE_BYTE_BINARY(add_byte);
+ VAL_WORD_WORD_BINARY(add_word);
+ VAL_LONG_LONG_BINARY(add_long);
+
+ VAL_BYTE_BYTE_BINARY(and_byte);
+ VAL_WORD_WORD_BINARY(and_word);
+ VAL_LONG_LONG_BINARY(and_long);
+
+ VAL_BYTE_BYTE_BINARY(cmp_byte);
+ VAL_WORD_WORD_BINARY(cmp_word);
+ VAL_LONG_LONG_BINARY(cmp_long);
+
+ VAL_BYTE_UNARY(daa_byte);
+ VAL_BYTE_UNARY(das_byte); // Fails for 0x9A (out of range anyway)
+
+ VAL_BYTE_UNARY(dec_byte);
+ VAL_WORD_UNARY(dec_word);
+ VAL_LONG_UNARY(dec_long);
+
+ VAL_BYTE_UNARY(inc_byte);
+ VAL_WORD_UNARY(inc_word);
+ VAL_LONG_UNARY(inc_long);
+
+ VAL_BYTE_BYTE_BINARY(or_byte);
+ VAL_WORD_WORD_BINARY(or_word);
+ VAL_LONG_LONG_BINARY(or_long);
+
+ VAL_BYTE_UNARY(neg_byte);
+ VAL_WORD_UNARY(neg_word);
+ VAL_LONG_UNARY(neg_long);
+
+ VAL_BYTE_UNARY(not_byte);
+ VAL_WORD_UNARY(not_word);
+ VAL_LONG_UNARY(not_long);
+
+ VAL_BYTE_ROTATE(rcl_byte);
+ VAL_WORD_ROTATE(rcl_word);
+ VAL_LONG_ROTATE(rcl_long);
+
+ VAL_BYTE_ROTATE(rcr_byte);
+ VAL_WORD_ROTATE(rcr_word);
+ VAL_LONG_ROTATE(rcr_long);
+
+ VAL_BYTE_ROTATE(rol_byte);
+ VAL_WORD_ROTATE(rol_word);
+ VAL_LONG_ROTATE(rol_long);
+
+ VAL_BYTE_ROTATE(ror_byte);
+ VAL_WORD_ROTATE(ror_word);
+ VAL_LONG_ROTATE(ror_long);
+
+ VAL_BYTE_ROTATE(shl_byte);
+ VAL_WORD_ROTATE(shl_word);
+ VAL_LONG_ROTATE(shl_long);
+
+ VAL_BYTE_ROTATE(shr_byte);
+ VAL_WORD_ROTATE(shr_word);
+ VAL_LONG_ROTATE(shr_long);
+
+ VAL_BYTE_ROTATE(sar_byte);
+ VAL_WORD_ROTATE(sar_word);
+ VAL_LONG_ROTATE(sar_long);
+
+ VAL_WORD_ROTATE_DBL(shld_word);
+ VAL_LONG_ROTATE_DBL(shld_long);
+
+ VAL_WORD_ROTATE_DBL(shrd_word);
+ VAL_LONG_ROTATE_DBL(shrd_long);
+
+ VAL_BYTE_BYTE_BINARY(sbb_byte);
+ VAL_WORD_WORD_BINARY(sbb_word);
+ VAL_LONG_LONG_BINARY(sbb_long);
+
+ VAL_BYTE_BYTE_BINARY(sub_byte);
+ VAL_WORD_WORD_BINARY(sub_word);
+ VAL_LONG_LONG_BINARY(sub_long);
+
+ VAL_BYTE_BYTE_BINARY(xor_byte);
+ VAL_WORD_WORD_BINARY(xor_word);
+ VAL_LONG_LONG_BINARY(xor_long);
+
+ VAL_VOID_BYTE_BINARY(test_byte);
+ VAL_VOID_WORD_BINARY(test_word);
+ VAL_VOID_LONG_BINARY(test_long);
+
+ VAL_BYTE_MUL(imul_byte);
+ VAL_WORD_MUL(imul_word);
+ VAL_LONG_MUL(imul_long);
+
+ VAL_BYTE_MUL(mul_byte);
+ VAL_WORD_MUL(mul_word);
+ VAL_LONG_MUL(mul_long);
+
+ VAL_BYTE_DIV(idiv_byte);
+ VAL_WORD_DIV(idiv_word);
+ VAL_LONG_DIV(idiv_long);
+
+ VAL_BYTE_DIV(div_byte);
+ VAL_WORD_DIV(div_word);
+ VAL_LONG_DIV(div_long);
+
+ return 0;
+}
diff --git a/cfe/cfe/x86emu/x86emu.h b/cfe/cfe/x86emu/x86emu.h
new file mode 100644
index 0000000..7c7d367
--- /dev/null
+++ b/cfe/cfe/x86emu/x86emu.h
@@ -0,0 +1,198 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for public specific functions.
+* Any application linking against us should only
+* include this header
+*
+****************************************************************************/
+/* $XFree86: xc/extras/x86emu/include/x86emu.h,v 1.2 2000/11/21 23:10:25 tsi Exp $ */
+
+#ifndef __X86EMU_X86EMU_H
+#define __X86EMU_X86EMU_H
+
+#ifdef SCITECH
+#include "scitech.h"
+#define X86API _ASMAPI
+#define X86APIP _ASMAPIP
+typedef int X86EMU_pioAddr;
+#else
+#include "x86emu/types.h"
+#define X86API
+#define X86APIP *
+#endif
+#include "x86emu/regs.h"
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+#ifndef __mips
+#pragma pack(1)
+#endif
+
+/****************************************************************************
+REMARKS:
+Data structure containing ponters to programmed I/O functions used by the
+emulator. This is used so that the user program can hook all programmed
+I/O for the emulator to handled as necessary by the user program. By
+default the emulator contains simple functions that do not do access the
+hardware in any way. To allow the emualtor access the hardware, you will
+need to override the programmed I/O functions using the X86EMU_setupPioFuncs
+function.
+
+HEADER:
+x86emu.h
+
+MEMBERS:
+inb - Function to read a byte from an I/O port
+inw - Function to read a word from an I/O port
+inl - Function to read a dword from an I/O port
+outb - Function to write a byte to an I/O port
+outw - Function to write a word to an I/O port
+outl - Function to write a dword to an I/O port
+****************************************************************************/
+typedef struct {
+ u8 (X86APIP inb)(X86EMU_pioAddr addr);
+ u16 (X86APIP inw)(X86EMU_pioAddr addr);
+ u32 (X86APIP inl)(X86EMU_pioAddr addr);
+ void (X86APIP outb)(X86EMU_pioAddr addr, u8 val);
+ void (X86APIP outw)(X86EMU_pioAddr addr, u16 val);
+ void (X86APIP outl)(X86EMU_pioAddr addr, u32 val);
+ } X86EMU_pioFuncs;
+
+/****************************************************************************
+REMARKS:
+Data structure containing ponters to memory access functions used by the
+emulator. This is used so that the user program can hook all memory
+access functions as necessary for the emulator. By default the emulator
+contains simple functions that only access the internal memory of the
+emulator. If you need specialised functions to handle access to different
+types of memory (ie: hardware framebuffer accesses and BIOS memory access
+etc), you will need to override this using the X86EMU_setupMemFuncs
+function.
+
+HEADER:
+x86emu.h
+
+MEMBERS:
+rdb - Function to read a byte from an address
+rdw - Function to read a word from an address
+rdl - Function to read a dword from an address
+wrb - Function to write a byte to an address
+wrw - Function to write a word to an address
+wrl - Function to write a dword to an address
+****************************************************************************/
+typedef struct {
+ u8 (X86APIP rdb)(u32 addr);
+ u16 (X86APIP rdw)(u32 addr);
+ u32 (X86APIP rdl)(u32 addr);
+ void (X86APIP wrb)(u32 addr, u8 val);
+ void (X86APIP wrw)(u32 addr, u16 val);
+ void (X86APIP wrl)(u32 addr, u32 val);
+ } X86EMU_memFuncs;
+
+/****************************************************************************
+ Here are the default memory read and write
+ function in case they are needed as fallbacks.
+***************************************************************************/
+extern u8 X86API rdb(u32 addr);
+extern u16 X86API rdw(u32 addr);
+extern u32 X86API rdl(u32 addr);
+extern void X86API wrb(u32 addr, u8 val);
+extern void X86API wrw(u32 addr, u16 val);
+extern void X86API wrl(u32 addr, u32 val);
+
+#ifndef __mips
+#pragma pack()
+#endif
+
+/*--------------------- type definitions -----------------------------------*/
+
+typedef void (X86APIP X86EMU_intrFuncs)(int num);
+extern X86EMU_intrFuncs _X86EMU_intrTab[256];
+
+/*-------------------------- Function Prototypes --------------------------*/
+
+#ifdef __cplusplus
+extern "C" { /* Use "C" linkage when in C++ mode */
+#endif
+
+void X86EMU_setupMemFuncs(X86EMU_memFuncs *funcs);
+void X86EMU_setupPioFuncs(X86EMU_pioFuncs *funcs);
+void X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[]);
+void X86EMU_prepareForInt(int num);
+
+/* decode.c */
+
+void X86EMU_exec(void);
+void X86EMU_halt_sys(void);
+
+#ifdef DEBUG
+#define HALT_SYS() \
+ printk("halt_sys: file %s, line %d\n", __FILE__, __LINE__), \
+ X86EMU_halt_sys()
+#else
+#define HALT_SYS() X86EMU_halt_sys()
+#endif
+
+/* Debug options */
+
+#define DEBUG_DECODE_F 0x000001 /* print decoded instruction */
+#define DEBUG_TRACE_F 0x000002 /* dump regs before/after execution */
+#define DEBUG_STEP_F 0x000004
+#define DEBUG_DISASSEMBLE_F 0x000008
+#define DEBUG_BREAK_F 0x000010
+#define DEBUG_SVC_F 0x000020
+#define DEBUG_FS_F 0x000080
+#define DEBUG_PROC_F 0x000100
+#define DEBUG_SYSINT_F 0x000200 /* bios system interrupts. */
+#define DEBUG_TRACECALL_F 0x000400
+#define DEBUG_INSTRUMENT_F 0x000800
+#define DEBUG_MEM_TRACE_F 0x001000
+#define DEBUG_IO_TRACE_F 0x002000
+#define DEBUG_TRACECALL_REGS_F 0x004000
+#define DEBUG_DECODE_NOPRINT_F 0x008000
+#define DEBUG_SAVE_IP_CS_F 0x010000
+#define DEBUG_SYS_F (DEBUG_SVC_F|DEBUG_FS_F|DEBUG_PROC_F)
+
+void X86EMU_trace_regs(void);
+void X86EMU_trace_xregs(void);
+void X86EMU_dump_memory(u16 seg, u16 off, u32 amt);
+int X86EMU_trace_on(void);
+int X86EMU_trace_off(void);
+
+#ifdef __cplusplus
+} /* End of "C" linkage for C++ */
+#endif
+
+#endif /* __X86EMU_X86EMU_H */
diff --git a/cfe/cfe/x86emu/x86emu/debug.h b/cfe/cfe/x86emu/x86emu/debug.h
new file mode 100644
index 0000000..45271c9
--- /dev/null
+++ b/cfe/cfe/x86emu/x86emu/debug.h
@@ -0,0 +1,212 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for debug definitions.
+*
+****************************************************************************/
+/* $XFree86: xc/extras/x86emu/src/x86emu/x86emu/debug.h,v 1.4 2000/11/21 23:10:27 tsi Exp $ */
+
+#ifndef __X86EMU_DEBUG_H
+#define __X86EMU_DEBUG_H
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+/* checks to be enabled for "runtime" */
+
+#define CHECK_IP_FETCH_F 0x1
+#define CHECK_SP_ACCESS_F 0x2
+#define CHECK_MEM_ACCESS_F 0x4 /*using regular linear pointer */
+#define CHECK_DATA_ACCESS_F 0x8 /*using segment:offset*/
+
+#ifdef DEBUG
+# define CHECK_IP_FETCH() (M.x86.check & CHECK_IP_FETCH_F)
+# define CHECK_SP_ACCESS() (M.x86.check & CHECK_SP_ACCESS_F)
+# define CHECK_MEM_ACCESS() (M.x86.check & CHECK_MEM_ACCESS_F)
+# define CHECK_DATA_ACCESS() (M.x86.check & CHECK_DATA_ACCESS_F)
+#else
+# define CHECK_IP_FETCH()
+# define CHECK_SP_ACCESS()
+# define CHECK_MEM_ACCESS()
+# define CHECK_DATA_ACCESS()
+#endif
+
+#ifdef DEBUG
+# define DEBUG_INSTRUMENT() (M.x86.debug & DEBUG_INSTRUMENT_F)
+# define DEBUG_DECODE() (M.x86.debug & DEBUG_DECODE_F)
+# define DEBUG_TRACE() (M.x86.debug & DEBUG_TRACE_F)
+# define DEBUG_STEP() (M.x86.debug & DEBUG_STEP_F)
+# define DEBUG_DISASSEMBLE() (M.x86.debug & DEBUG_DISASSEMBLE_F)
+# define DEBUG_BREAK() (M.x86.debug & DEBUG_BREAK_F)
+# define DEBUG_SVC() (M.x86.debug & DEBUG_SVC_F)
+# define DEBUG_SAVE_IP_CS() (M.x86.debug & DEBUG_SAVE_IP_CS_F)
+
+# define DEBUG_FS() (M.x86.debug & DEBUG_FS_F)
+# define DEBUG_PROC() (M.x86.debug & DEBUG_PROC_F)
+# define DEBUG_SYSINT() (M.x86.debug & DEBUG_SYSINT_F)
+# define DEBUG_TRACECALL() (M.x86.debug & DEBUG_TRACECALL_F)
+# define DEBUG_TRACECALLREGS() (M.x86.debug & DEBUG_TRACECALL_REGS_F)
+# define DEBUG_SYS() (M.x86.debug & DEBUG_SYS_F)
+# define DEBUG_MEM_TRACE() (M.x86.debug & DEBUG_MEM_TRACE_F)
+# define DEBUG_IO_TRACE() (M.x86.debug & DEBUG_IO_TRACE_F)
+# define DEBUG_DECODE_NOPRINT() (M.x86.debug & DEBUG_DECODE_NOPRINT_F)
+#else
+# define DEBUG_INSTRUMENT() 0
+# define DEBUG_DECODE() 0
+# define DEBUG_TRACE() 0
+# define DEBUG_STEP() 0
+# define DEBUG_DISASSEMBLE() 0
+# define DEBUG_BREAK() 0
+# define DEBUG_SVC() 0
+# define DEBUG_SAVE_IP_CS() 0
+# define DEBUG_FS() 0
+# define DEBUG_PROC() 0
+# define DEBUG_SYSINT() 0
+# define DEBUG_TRACECALL() 0
+# define DEBUG_TRACECALLREGS() 0
+# define DEBUG_SYS() 0
+# define DEBUG_MEM_TRACE() 0
+# define DEBUG_IO_TRACE() 0
+# define DEBUG_DECODE_NOPRINT() 0
+#endif
+
+#ifdef DEBUG
+
+# define DECODE_PRINTF(x) if (DEBUG_DECODE()) \
+ x86emu_decode_printf(x)
+# define DECODE_PRINTF2(x,y) if (DEBUG_DECODE()) \
+ x86emu_decode_printf2(x,y)
+
+/*
+ * The following allow us to look at the bytes of an instruction. The
+ * first INCR_INSTRN_LEN, is called everytime bytes are consumed in
+ * the decoding process. The SAVE_IP_CS is called initially when the
+ * major opcode of the instruction is accessed.
+ */
+#define INC_DECODED_INST_LEN(x) \
+ if (DEBUG_DECODE()) \
+ x86emu_inc_decoded_inst_len(x)
+
+#define SAVE_IP_CS(x,y) \
+ if (DEBUG_DECODE() | DEBUG_TRACECALL() | DEBUG_BREAK() \
+ | DEBUG_IO_TRACE() | DEBUG_SAVE_IP_CS()) { \
+ M.x86.saved_cs = x; \
+ M.x86.saved_ip = y; \
+ }
+#else
+# define INC_DECODED_INST_LEN(x)
+# define DECODE_PRINTF(x)
+# define DECODE_PRINTF2(x,y)
+# define SAVE_IP_CS(x,y)
+#endif
+
+#ifdef DEBUG
+#define TRACE_REGS() \
+ if (DEBUG_DISASSEMBLE()) { \
+ x86emu_just_disassemble(); \
+ goto EndOfTheInstructionProcedure; \
+ } \
+ if (DEBUG_TRACE() || DEBUG_DECODE()) X86EMU_trace_regs()
+#else
+# define TRACE_REGS()
+#endif
+
+#ifdef DEBUG
+# define SINGLE_STEP() if (DEBUG_STEP()) x86emu_single_step()
+#else
+# define SINGLE_STEP()
+#endif
+
+#define TRACE_AND_STEP() \
+ TRACE_REGS(); \
+ SINGLE_STEP()
+
+#ifdef DEBUG
+# define START_OF_INSTR()
+# define END_OF_INSTR() EndOfTheInstructionProcedure: x86emu_end_instr();
+# define END_OF_INSTR_NO_TRACE() x86emu_end_instr();
+#else
+# define START_OF_INSTR()
+# define END_OF_INSTR()
+# define END_OF_INSTR_NO_TRACE()
+#endif
+
+#ifdef DEBUG
+# define CALL_TRACE(u,v,w,x,s) \
+ if (DEBUG_TRACECALLREGS()) \
+ x86emu_dump_regs(); \
+ if (DEBUG_TRACECALL()) \
+ printk("%04x:%04x: CALL %s%04x:%04x\n", u , v, s, w, x);
+# define RETURN_TRACE(n,u,v) \
+ if (DEBUG_TRACECALLREGS()) \
+ x86emu_dump_regs(); \
+ if (DEBUG_TRACECALL()) \
+ printk("%04x:%04x: %s\n",u,v,n);
+#else
+# define CALL_TRACE(u,v,w,x,s)
+# define RETURN_TRACE(n,u,v)
+#endif
+
+#ifdef DEBUG
+#define DB(x) x
+#else
+#define DB(x)
+#endif
+
+/*-------------------------- Function Prototypes --------------------------*/
+
+#ifdef __cplusplus
+extern "C" { /* Use "C" linkage when in C++ mode */
+#endif
+
+extern void x86emu_inc_decoded_inst_len (int x);
+extern void x86emu_decode_printf (char *x);
+extern void x86emu_decode_printf2 (char *x, int y);
+extern void x86emu_just_disassemble (void);
+extern void x86emu_single_step (void);
+extern void x86emu_end_instr (void);
+extern void x86emu_dump_regs (void);
+extern void x86emu_dump_xregs (void);
+extern void x86emu_print_int_vect (u16 iv);
+extern void x86emu_instrument_instruction (void);
+extern void x86emu_check_ip_access (void);
+extern void x86emu_check_sp_access (void);
+extern void x86emu_check_mem_access (u32 p);
+extern void x86emu_check_data_access (uint s, uint o);
+
+#ifdef __cplusplus
+} /* End of "C" linkage for C++ */
+#endif
+
+
+#endif /* __X86EMU_DEBUG_H */
diff --git a/cfe/cfe/x86emu/x86emu/decode.h b/cfe/cfe/x86emu/x86emu/decode.h
new file mode 100644
index 0000000..321a345
--- /dev/null
+++ b/cfe/cfe/x86emu/x86emu/decode.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for instruction decoding logic.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_DECODE_H
+#define __X86EMU_DECODE_H
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+/* Instruction Decoding Stuff */
+
+#define FETCH_DECODE_MODRM(mod,rh,rl) fetch_decode_modrm(&mod,&rh,&rl)
+#define DECODE_RM_BYTE_REGISTER(r) decode_rm_byte_register(r)
+#define DECODE_RM_WORD_REGISTER(r) decode_rm_word_register(r)
+#define DECODE_RM_LONG_REGISTER(r) decode_rm_long_register(r)
+#define DECODE_CLEAR_SEGOVR() M.x86.mode &= ~SYSMODE_CLRMASK
+
+/*-------------------------- Function Prototypes --------------------------*/
+
+#ifdef __cplusplus
+extern "C" { /* Use "C" linkage when in C++ mode */
+#endif
+
+void x86emu_intr_raise (u8 type);
+void fetch_decode_modrm (int *mod,int *regh,int *regl);
+u8 fetch_byte_imm (void);
+u16 fetch_word_imm (void);
+u32 fetch_long_imm (void);
+u8 fetch_data_byte (uint offset);
+u8 fetch_data_byte_abs (uint segment, uint offset);
+u16 fetch_data_word (uint offset);
+u16 fetch_data_word_abs (uint segment, uint offset);
+u32 fetch_data_long (uint offset);
+u32 fetch_data_long_abs (uint segment, uint offset);
+void store_data_byte (uint offset, u8 val);
+void store_data_byte_abs (uint segment, uint offset, u8 val);
+void store_data_word (uint offset, u16 val);
+void store_data_word_abs (uint segment, uint offset, u16 val);
+void store_data_long (uint offset, u32 val);
+void store_data_long_abs (uint segment, uint offset, u32 val);
+u8* decode_rm_byte_register(int reg);
+u16* decode_rm_word_register(int reg);
+u32* decode_rm_long_register(int reg);
+u16* decode_rm_seg_register(int reg);
+unsigned decode_rm00_address(int rm);
+unsigned decode_rm01_address(int rm);
+unsigned decode_rm10_address(int rm);
+
+#ifdef __cplusplus
+} /* End of "C" linkage for C++ */
+#endif
+
+#endif /* __X86EMU_DECODE_H */
diff --git a/cfe/cfe/x86emu/x86emu/fpu.h b/cfe/cfe/x86emu/x86emu/fpu.h
new file mode 100644
index 0000000..5fb2714
--- /dev/null
+++ b/cfe/cfe/x86emu/x86emu/fpu.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for FPU instruction decoding.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_FPU_H
+#define __X86EMU_FPU_H
+
+#ifdef __cplusplus
+extern "C" { /* Use "C" linkage when in C++ mode */
+#endif
+
+/* these have to be defined, whether 8087 support compiled in or not. */
+
+extern void x86emuOp_esc_coprocess_d8 (u8 op1);
+extern void x86emuOp_esc_coprocess_d9 (u8 op1);
+extern void x86emuOp_esc_coprocess_da (u8 op1);
+extern void x86emuOp_esc_coprocess_db (u8 op1);
+extern void x86emuOp_esc_coprocess_dc (u8 op1);
+extern void x86emuOp_esc_coprocess_dd (u8 op1);
+extern void x86emuOp_esc_coprocess_de (u8 op1);
+extern void x86emuOp_esc_coprocess_df (u8 op1);
+
+#ifdef __cplusplus
+} /* End of "C" linkage for C++ */
+#endif
+
+#endif /* __X86EMU_FPU_H */
diff --git a/cfe/cfe/x86emu/x86emu/fpu_regs.h b/cfe/cfe/x86emu/x86emu/fpu_regs.h
new file mode 100644
index 0000000..56e9a04
--- /dev/null
+++ b/cfe/cfe/x86emu/x86emu/fpu_regs.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for FPU register definitions.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_FPU_REGS_H
+#define __X86EMU_FPU_REGS_H
+
+#ifdef X86_FPU_SUPPORT
+
+#pragma pack(1)
+
+/* Basic 8087 register can hold any of the following values: */
+
+union x86_fpu_reg_u {
+ s8 tenbytes[10];
+ double dval;
+ float fval;
+ s16 sval;
+ s32 lval;
+ };
+
+struct x86_fpu_reg {
+ union x86_fpu_reg_u reg;
+ char tag;
+ };
+
+/*
+ * Since we are not going to worry about the problems of aliasing
+ * registers, every time a register is modified, its result type is
+ * set in the tag fields for that register. If some operation
+ * attempts to access the type in a way inconsistent with its current
+ * storage format, then we flag the operation. If common, we'll
+ * attempt the conversion.
+ */
+
+#define X86_FPU_VALID 0x80
+#define X86_FPU_REGTYP(r) ((r) & 0x7F)
+
+#define X86_FPU_WORD 0x0
+#define X86_FPU_SHORT 0x1
+#define X86_FPU_LONG 0x2
+#define X86_FPU_FLOAT 0x3
+#define X86_FPU_DOUBLE 0x4
+#define X86_FPU_LDBL 0x5
+#define X86_FPU_BSD 0x6
+
+#define X86_FPU_STKTOP 0
+
+struct x86_fpu_registers {
+ struct x86_fpu_reg x86_fpu_stack[8];
+ int x86_fpu_flags;
+ int x86_fpu_config; /* rounding modes, etc. */
+ short x86_fpu_tos, x86_fpu_bos;
+ };
+
+#pragma pack()
+
+/*
+ * There are two versions of the following macro.
+ *
+ * One version is for opcode D9, for which there are more than 32
+ * instructions encoded in the second byte of the opcode.
+ *
+ * The other version, deals with all the other 7 i87 opcodes, for
+ * which there are only 32 strings needed to describe the
+ * instructions.
+ */
+
+#endif /* X86_FPU_SUPPORT */
+
+#ifdef DEBUG
+# define DECODE_PRINTINSTR32(t,mod,rh,rl) \
+ DECODE_PRINTF(t[(mod<<3)+(rh)]);
+# define DECODE_PRINTINSTR256(t,mod,rh,rl) \
+ DECODE_PRINTF(t[(mod<<6)+(rh<<3)+(rl)]);
+#else
+# define DECODE_PRINTINSTR32(t,mod,rh,rl)
+# define DECODE_PRINTINSTR256(t,mod,rh,rl)
+#endif
+
+#endif /* __X86EMU_FPU_REGS_H */
diff --git a/cfe/cfe/x86emu/x86emu/ops.h b/cfe/cfe/x86emu/x86emu/ops.h
new file mode 100644
index 0000000..65ea676
--- /dev/null
+++ b/cfe/cfe/x86emu/x86emu/ops.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for operand decoding functions.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_OPS_H
+#define __X86EMU_OPS_H
+
+extern void (*x86emu_optab[0x100])(u8 op1);
+extern void (*x86emu_optab2[0x100])(u8 op2);
+
+#endif /* __X86EMU_OPS_H */
diff --git a/cfe/cfe/x86emu/x86emu/ops_protos.h b/cfe/cfe/x86emu/x86emu/ops_protos.h
new file mode 100644
index 0000000..8787c5a
--- /dev/null
+++ b/cfe/cfe/x86emu/x86emu/ops_protos.h
@@ -0,0 +1,277 @@
+
+#define OPPROTO(x) void x(u8)
+
+OPPROTO(x86emuOp_illegal_op);
+OPPROTO(x86emuOp_add_byte_RM_R);
+OPPROTO(x86emuOp_add_word_RM_R);
+OPPROTO(x86emuOp_add_byte_R_RM);
+OPPROTO(x86emuOp_add_word_R_RM);
+OPPROTO(x86emuOp_add_byte_AL_IMM);
+OPPROTO(x86emuOp_add_word_AX_IMM);
+OPPROTO(x86emuOp_push_ES);
+OPPROTO(x86emuOp_pop_ES);
+OPPROTO(x86emuOp_or_byte_RM_R);
+OPPROTO(x86emuOp_or_word_RM_R);
+OPPROTO(x86emuOp_or_byte_R_RM);
+OPPROTO(x86emuOp_or_word_R_RM);
+OPPROTO(x86emuOp_or_byte_AL_IMM);
+OPPROTO(x86emuOp_or_word_AX_IMM);
+OPPROTO(x86emuOp_push_CS);
+OPPROTO(x86emuOp_two_byte);
+OPPROTO(x86emuOp_adc_byte_RM_R);
+OPPROTO(x86emuOp_adc_word_RM_R);
+OPPROTO(x86emuOp_adc_byte_R_RM);
+OPPROTO(x86emuOp_adc_word_R_RM);
+OPPROTO(x86emuOp_adc_byte_AL_IMM);
+OPPROTO(x86emuOp_adc_word_AX_IMM);
+OPPROTO(x86emuOp_push_SS);
+OPPROTO(x86emuOp_pop_SS);
+OPPROTO(x86emuOp_sbb_byte_RM_R);
+OPPROTO(x86emuOp_sbb_word_RM_R);
+OPPROTO(x86emuOp_sbb_byte_R_RM);
+OPPROTO(x86emuOp_sbb_word_R_RM);
+OPPROTO(x86emuOp_sbb_byte_AL_IMM);
+OPPROTO(x86emuOp_sbb_word_AX_IMM);
+OPPROTO(x86emuOp_push_DS);
+OPPROTO(x86emuOp_pop_DS);
+OPPROTO(x86emuOp_and_byte_RM_R);
+OPPROTO(x86emuOp_and_word_RM_R);
+OPPROTO(x86emuOp_and_byte_R_RM);
+OPPROTO(x86emuOp_and_word_R_RM);
+OPPROTO(x86emuOp_and_byte_AL_IMM);
+OPPROTO(x86emuOp_and_word_AX_IMM);
+OPPROTO(x86emuOp_segovr_ES);
+OPPROTO(x86emuOp_daa);
+OPPROTO(x86emuOp_sub_byte_RM_R);
+OPPROTO(x86emuOp_sub_word_RM_R);
+OPPROTO(x86emuOp_sub_byte_R_RM);
+OPPROTO(x86emuOp_sub_word_R_RM);
+OPPROTO(x86emuOp_sub_byte_AL_IMM);
+OPPROTO(x86emuOp_sub_word_AX_IMM);
+OPPROTO(x86emuOp_segovr_CS);
+OPPROTO(x86emuOp_das);
+OPPROTO(x86emuOp_xor_byte_RM_R);
+OPPROTO(x86emuOp_xor_word_RM_R);
+OPPROTO(x86emuOp_xor_byte_R_RM);
+OPPROTO(x86emuOp_xor_word_R_RM);
+OPPROTO(x86emuOp_xor_byte_AL_IMM);
+OPPROTO(x86emuOp_xor_word_AX_IMM);
+OPPROTO(x86emuOp_segovr_SS);
+OPPROTO(x86emuOp_aaa);
+OPPROTO(x86emuOp_cmp_byte_RM_R);
+OPPROTO(x86emuOp_cmp_word_RM_R);
+OPPROTO(x86emuOp_cmp_byte_R_RM);
+OPPROTO(x86emuOp_cmp_word_R_RM);
+OPPROTO(x86emuOp_cmp_byte_AL_IMM);
+OPPROTO(x86emuOp_cmp_word_AX_IMM);
+OPPROTO(x86emuOp_segovr_DS);
+OPPROTO(x86emuOp_aas);
+OPPROTO(x86emuOp_inc_AX);
+OPPROTO(x86emuOp_inc_CX);
+OPPROTO(x86emuOp_inc_DX);
+OPPROTO(x86emuOp_inc_BX);
+OPPROTO(x86emuOp_inc_SP);
+OPPROTO(x86emuOp_inc_BP);
+OPPROTO(x86emuOp_inc_SI);
+OPPROTO(x86emuOp_inc_DI);
+OPPROTO(x86emuOp_dec_AX);
+OPPROTO(x86emuOp_dec_CX);
+OPPROTO(x86emuOp_dec_DX);
+OPPROTO(x86emuOp_dec_BX);
+OPPROTO(x86emuOp_dec_SP);
+OPPROTO(x86emuOp_dec_BP);
+OPPROTO(x86emuOp_dec_SI);
+OPPROTO(x86emuOp_dec_DI);
+OPPROTO(x86emuOp_push_AX);
+OPPROTO(x86emuOp_push_CX);
+OPPROTO(x86emuOp_push_DX);
+OPPROTO(x86emuOp_push_BX);
+OPPROTO(x86emuOp_push_SP);
+OPPROTO(x86emuOp_push_BP);
+OPPROTO(x86emuOp_push_SI);
+OPPROTO(x86emuOp_push_DI);
+OPPROTO(x86emuOp_pop_AX);
+OPPROTO(x86emuOp_pop_CX);
+OPPROTO(x86emuOp_pop_DX);
+OPPROTO(x86emuOp_pop_BX);
+OPPROTO(x86emuOp_pop_SP);
+OPPROTO(x86emuOp_pop_BP);
+OPPROTO(x86emuOp_pop_SI);
+OPPROTO(x86emuOp_pop_DI);
+OPPROTO(x86emuOp_push_all);
+OPPROTO(x86emuOp_pop_all);
+OPPROTO(x86emuOp_segovr_FS);
+OPPROTO(x86emuOp_segovr_GS);
+OPPROTO(x86emuOp_prefix_data);
+OPPROTO(x86emuOp_prefix_addr);
+OPPROTO(x86emuOp_push_word_IMM);
+OPPROTO(x86emuOp_imul_word_IMM);
+OPPROTO(x86emuOp_push_byte_IMM);
+OPPROTO(x86emuOp_imul_byte_IMM);
+OPPROTO(x86emuOp_ins_byte);
+OPPROTO(x86emuOp_ins_word);
+OPPROTO(x86emuOp_outs_byte);
+OPPROTO(x86emuOp_outs_word);
+OPPROTO(x86emuOp_jump_near_O);
+OPPROTO(x86emuOp_jump_near_NO);
+OPPROTO(x86emuOp_jump_near_B);
+OPPROTO(x86emuOp_jump_near_NB);
+OPPROTO(x86emuOp_jump_near_Z);
+OPPROTO(x86emuOp_jump_near_NZ);
+OPPROTO(x86emuOp_jump_near_BE);
+OPPROTO(x86emuOp_jump_near_NBE);
+OPPROTO(x86emuOp_jump_near_S);
+OPPROTO(x86emuOp_jump_near_NS);
+OPPROTO(x86emuOp_jump_near_P);
+OPPROTO(x86emuOp_jump_near_NP);
+OPPROTO(x86emuOp_jump_near_L);
+OPPROTO(x86emuOp_jump_near_NL);
+OPPROTO(x86emuOp_jump_near_LE);
+OPPROTO(x86emuOp_jump_near_NLE);
+OPPROTO(x86emuOp_opc80_byte_RM_IMM);
+OPPROTO(x86emuOp_opc81_word_RM_IMM);
+OPPROTO(x86emuOp_opc82_byte_RM_IMM);
+OPPROTO(x86emuOp_opc83_word_RM_IMM);
+OPPROTO(x86emuOp_test_byte_RM_R);
+OPPROTO(x86emuOp_test_word_RM_R);
+OPPROTO(x86emuOp_xchg_byte_RM_R);
+OPPROTO(x86emuOp_xchg_word_RM_R);
+OPPROTO(x86emuOp_mov_byte_RM_R);
+OPPROTO(x86emuOp_mov_word_RM_R);
+OPPROTO(x86emuOp_mov_byte_R_RM);
+OPPROTO(x86emuOp_mov_word_R_RM);
+OPPROTO(x86emuOp_mov_word_RM_SR);
+OPPROTO(x86emuOp_lea_word_R_M);
+OPPROTO(x86emuOp_mov_word_SR_RM);
+OPPROTO(x86emuOp_pop_RM);
+OPPROTO(x86emuOp_nop);
+OPPROTO(x86emuOp_xchg_word_AX_CX);
+OPPROTO(x86emuOp_xchg_word_AX_DX);
+OPPROTO(x86emuOp_xchg_word_AX_BX);
+OPPROTO(x86emuOp_xchg_word_AX_SP);
+OPPROTO(x86emuOp_xchg_word_AX_BP);
+OPPROTO(x86emuOp_xchg_word_AX_SI);
+OPPROTO(x86emuOp_xchg_word_AX_DI);
+OPPROTO(x86emuOp_cbw);
+OPPROTO(x86emuOp_cwd);
+OPPROTO(x86emuOp_call_far_IMM);
+OPPROTO(x86emuOp_wait);
+OPPROTO(x86emuOp_pushf_word);
+OPPROTO(x86emuOp_popf_word);
+OPPROTO(x86emuOp_sahf);
+OPPROTO(x86emuOp_lahf);
+OPPROTO(x86emuOp_mov_AL_M_IMM);
+OPPROTO(x86emuOp_mov_AX_M_IMM);
+OPPROTO(x86emuOp_mov_M_AL_IMM);
+OPPROTO(x86emuOp_mov_M_AX_IMM);
+OPPROTO(x86emuOp_movs_byte);
+OPPROTO(x86emuOp_movs_word);
+OPPROTO(x86emuOp_cmps_byte);
+OPPROTO(x86emuOp_cmps_word);
+OPPROTO(x86emuOp_test_AL_IMM);
+OPPROTO(x86emuOp_test_AX_IMM);
+OPPROTO(x86emuOp_stos_byte);
+OPPROTO(x86emuOp_stos_word);
+OPPROTO(x86emuOp_lods_byte);
+OPPROTO(x86emuOp_lods_word);
+OPPROTO(x86emuOp_scas_byte);
+OPPROTO(x86emuOp_scas_word);
+OPPROTO(x86emuOp_mov_byte_AL_IMM);
+OPPROTO(x86emuOp_mov_byte_CL_IMM);
+OPPROTO(x86emuOp_mov_byte_DL_IMM);
+OPPROTO(x86emuOp_mov_byte_BL_IMM);
+OPPROTO(x86emuOp_mov_byte_AH_IMM);
+OPPROTO(x86emuOp_mov_byte_CH_IMM);
+OPPROTO(x86emuOp_mov_byte_DH_IMM);
+OPPROTO(x86emuOp_mov_byte_BH_IMM);
+OPPROTO(x86emuOp_mov_word_AX_IMM);
+OPPROTO(x86emuOp_mov_word_CX_IMM);
+OPPROTO(x86emuOp_mov_word_DX_IMM);
+OPPROTO(x86emuOp_mov_word_BX_IMM);
+OPPROTO(x86emuOp_mov_word_SP_IMM);
+OPPROTO(x86emuOp_mov_word_BP_IMM);
+OPPROTO(x86emuOp_mov_word_SI_IMM);
+OPPROTO(x86emuOp_mov_word_DI_IMM);
+OPPROTO(x86emuOp_opcC0_byte_RM_MEM);
+OPPROTO(x86emuOp_opcC1_word_RM_MEM);
+OPPROTO(x86emuOp_ret_near_IMM);
+OPPROTO(x86emuOp_ret_near);
+OPPROTO(x86emuOp_les_R_IMM);
+OPPROTO(x86emuOp_lds_R_IMM);
+OPPROTO(x86emuOp_mov_byte_RM_IMM);
+OPPROTO(x86emuOp_mov_word_RM_IMM);
+OPPROTO(x86emuOp_enter);
+OPPROTO(x86emuOp_leave);
+OPPROTO(x86emuOp_ret_far_IMM);
+OPPROTO(x86emuOp_ret_far);
+OPPROTO(x86emuOp_int3);
+OPPROTO(x86emuOp_int_IMM);
+OPPROTO(x86emuOp_into);
+OPPROTO(x86emuOp_iret);
+OPPROTO(x86emuOp_opcD0_byte_RM_1);
+OPPROTO(x86emuOp_opcD1_word_RM_1);
+OPPROTO(x86emuOp_opcD2_byte_RM_CL);
+OPPROTO(x86emuOp_opcD3_word_RM_CL);
+OPPROTO(x86emuOp_aam);
+OPPROTO(x86emuOp_aad);
+OPPROTO(x86emuOp_xlat);
+OPPROTO(x86emuOp_loopne);
+OPPROTO(x86emuOp_loope);
+OPPROTO(x86emuOp_loop);
+OPPROTO(x86emuOp_jcxz);
+OPPROTO(x86emuOp_in_byte_AL_IMM);
+OPPROTO(x86emuOp_in_word_AX_IMM);
+OPPROTO(x86emuOp_out_byte_IMM_AL);
+OPPROTO(x86emuOp_out_word_IMM_AX);
+OPPROTO(x86emuOp_call_near_IMM);
+OPPROTO(x86emuOp_jump_near_IMM);
+OPPROTO(x86emuOp_jump_far_IMM);
+OPPROTO(x86emuOp_jump_byte_IMM);
+OPPROTO(x86emuOp_in_byte_AL_DX);
+OPPROTO(x86emuOp_in_word_AX_DX);
+OPPROTO(x86emuOp_out_byte_DX_AL);
+OPPROTO(x86emuOp_out_word_DX_AX);
+OPPROTO(x86emuOp_lock);
+OPPROTO(x86emuOp_repne);
+OPPROTO(x86emuOp_repe);
+OPPROTO(x86emuOp_halt);
+OPPROTO(x86emuOp_cmc);
+OPPROTO(x86emuOp_opcF6_byte_RM);
+OPPROTO(x86emuOp_opcF7_word_RM);
+OPPROTO(x86emuOp_clc);
+OPPROTO(x86emuOp_stc);
+OPPROTO(x86emuOp_cli);
+OPPROTO(x86emuOp_sti);
+OPPROTO(x86emuOp_cld);
+OPPROTO(x86emuOp_std);
+OPPROTO(x86emuOp_opcFE_byte_RM);
+OPPROTO(x86emuOp_opcFF_word_RM);
+
+
+OPPROTO(x86emuOp2_illegal_op);
+OPPROTO(x86emuOp2_long_jump);
+OPPROTO(x86emuOp2_set_byte);
+OPPROTO(x86emuOp2_push_FS);
+OPPROTO(x86emuOp2_pop_FS);
+OPPROTO(x86emuOp2_bt_R);
+OPPROTO(x86emuOp2_shld_IMM);
+OPPROTO(x86emuOp2_shld_CL);
+OPPROTO(x86emuOp2_push_GS);
+OPPROTO(x86emuOp2_pop_GS);
+OPPROTO(x86emuOp2_bts_R);
+OPPROTO(x86emuOp2_shrd_IMM);
+OPPROTO(x86emuOp2_shrd_CL);
+OPPROTO(x86emuOp2_imul_R_RM);
+OPPROTO(x86emuOp2_lss_R_IMM);
+OPPROTO(x86emuOp2_btr_R);
+OPPROTO(x86emuOp2_lfs_R_IMM);
+OPPROTO(x86emuOp2_lgs_R_IMM);
+OPPROTO(x86emuOp2_movzx_byte_R_RM);
+OPPROTO(x86emuOp2_movzx_word_R_RM);
+OPPROTO(x86emuOp2_btX_I);
+OPPROTO(x86emuOp2_btc_R);
+OPPROTO(x86emuOp2_bsf);
+OPPROTO(x86emuOp2_bsr);
+OPPROTO(x86emuOp2_movsx_byte_R_RM);
+OPPROTO(x86emuOp2_movsx_word_R_R);
+OPPROTO(x86emuOp2_movsx_word_R_RM);
diff --git a/cfe/cfe/x86emu/x86emu/prim_asm.h b/cfe/cfe/x86emu/x86emu/prim_asm.h
new file mode 100644
index 0000000..4fa8d55
--- /dev/null
+++ b/cfe/cfe/x86emu/x86emu/prim_asm.h
@@ -0,0 +1,971 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: Watcom C++ 10.6 or later
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Inline assembler versions of the primitive operand
+* functions for faster performance. At the moment this is
+* x86 inline assembler, but these functions could be replaced
+* with native inline assembler for each supported processor
+* platform.
+*
+****************************************************************************/
+/* $XFree86: xc/extras/x86emu/src/x86emu/x86emu/prim_asm.h,v 1.3 2000/04/19 15:48:15 tsi Exp $ */
+
+#ifndef __X86EMU_PRIM_ASM_H
+#define __X86EMU_PRIM_ASM_H
+
+#ifdef __WATCOMC__
+
+#ifndef VALIDATE
+#define __HAVE_INLINE_ASSEMBLER__
+#endif
+
+u32 get_flags_asm(void);
+#pragma aux get_flags_asm = \
+ "pushf" \
+ "pop eax" \
+ value [eax] \
+ modify exact [eax];
+
+u16 aaa_word_asm(u32 *flags,u16 d);
+#pragma aux aaa_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "aaa" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] \
+ value [ax] \
+ modify exact [ax];
+
+u16 aas_word_asm(u32 *flags,u16 d);
+#pragma aux aas_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "aas" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] \
+ value [ax] \
+ modify exact [ax];
+
+u16 aad_word_asm(u32 *flags,u16 d);
+#pragma aux aad_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "aad" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] \
+ value [ax] \
+ modify exact [ax];
+
+u16 aam_word_asm(u32 *flags,u8 d);
+#pragma aux aam_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "aam" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] \
+ value [ax] \
+ modify exact [ax];
+
+u8 adc_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux adc_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "adc al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ value [al] \
+ modify exact [al bl];
+
+u16 adc_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux adc_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "adc ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ value [ax] \
+ modify exact [ax bx];
+
+u32 adc_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux adc_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "adc eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ value [eax] \
+ modify exact [eax ebx];
+
+u8 add_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux add_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "add al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ value [al] \
+ modify exact [al bl];
+
+u16 add_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux add_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "add ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ value [ax] \
+ modify exact [ax bx];
+
+u32 add_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux add_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "add eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ value [eax] \
+ modify exact [eax ebx];
+
+u8 and_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux and_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "and al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ value [al] \
+ modify exact [al bl];
+
+u16 and_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux and_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "and ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ value [ax] \
+ modify exact [ax bx];
+
+u32 and_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux and_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "and eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ value [eax] \
+ modify exact [eax ebx];
+
+u8 cmp_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux cmp_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "cmp al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ value [al] \
+ modify exact [al bl];
+
+u16 cmp_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux cmp_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "cmp ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ value [ax] \
+ modify exact [ax bx];
+
+u32 cmp_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux cmp_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "cmp eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ value [eax] \
+ modify exact [eax ebx];
+
+u8 daa_byte_asm(u32 *flags,u8 d);
+#pragma aux daa_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "daa" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] \
+ value [al] \
+ modify exact [al];
+
+u8 das_byte_asm(u32 *flags,u8 d);
+#pragma aux das_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "das" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] \
+ value [al] \
+ modify exact [al];
+
+u8 dec_byte_asm(u32 *flags,u8 d);
+#pragma aux dec_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "dec al" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] \
+ value [al] \
+ modify exact [al];
+
+u16 dec_word_asm(u32 *flags,u16 d);
+#pragma aux dec_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "dec ax" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] \
+ value [ax] \
+ modify exact [ax];
+
+u32 dec_long_asm(u32 *flags,u32 d);
+#pragma aux dec_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "dec eax" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] \
+ value [eax] \
+ modify exact [eax];
+
+u8 inc_byte_asm(u32 *flags,u8 d);
+#pragma aux inc_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "inc al" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] \
+ value [al] \
+ modify exact [al];
+
+u16 inc_word_asm(u32 *flags,u16 d);
+#pragma aux inc_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "inc ax" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] \
+ value [ax] \
+ modify exact [ax];
+
+u32 inc_long_asm(u32 *flags,u32 d);
+#pragma aux inc_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "inc eax" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] \
+ value [eax] \
+ modify exact [eax];
+
+u8 or_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux or_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "or al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ value [al] \
+ modify exact [al bl];
+
+u16 or_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux or_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "or ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ value [ax] \
+ modify exact [ax bx];
+
+u32 or_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux or_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "or eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ value [eax] \
+ modify exact [eax ebx];
+
+u8 neg_byte_asm(u32 *flags,u8 d);
+#pragma aux neg_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "neg al" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] \
+ value [al] \
+ modify exact [al];
+
+u16 neg_word_asm(u32 *flags,u16 d);
+#pragma aux neg_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "neg ax" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] \
+ value [ax] \
+ modify exact [ax];
+
+u32 neg_long_asm(u32 *flags,u32 d);
+#pragma aux neg_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "neg eax" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] \
+ value [eax] \
+ modify exact [eax];
+
+u8 not_byte_asm(u32 *flags,u8 d);
+#pragma aux not_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "not al" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] \
+ value [al] \
+ modify exact [al];
+
+u16 not_word_asm(u32 *flags,u16 d);
+#pragma aux not_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "not ax" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] \
+ value [ax] \
+ modify exact [ax];
+
+u32 not_long_asm(u32 *flags,u32 d);
+#pragma aux not_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "not eax" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] \
+ value [eax] \
+ modify exact [eax];
+
+u8 rcl_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux rcl_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "rcl al,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [cl] \
+ value [al] \
+ modify exact [al cl];
+
+u16 rcl_word_asm(u32 *flags,u16 d, u8 s);
+#pragma aux rcl_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "rcl ax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [cl] \
+ value [ax] \
+ modify exact [ax cl];
+
+u32 rcl_long_asm(u32 *flags,u32 d, u8 s);
+#pragma aux rcl_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "rcl eax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [cl] \
+ value [eax] \
+ modify exact [eax cl];
+
+u8 rcr_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux rcr_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "rcr al,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [cl] \
+ value [al] \
+ modify exact [al cl];
+
+u16 rcr_word_asm(u32 *flags,u16 d, u8 s);
+#pragma aux rcr_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "rcr ax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [cl] \
+ value [ax] \
+ modify exact [ax cl];
+
+u32 rcr_long_asm(u32 *flags,u32 d, u8 s);
+#pragma aux rcr_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "rcr eax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [cl] \
+ value [eax] \
+ modify exact [eax cl];
+
+u8 rol_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux rol_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "rol al,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [cl] \
+ value [al] \
+ modify exact [al cl];
+
+u16 rol_word_asm(u32 *flags,u16 d, u8 s);
+#pragma aux rol_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "rol ax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [cl] \
+ value [ax] \
+ modify exact [ax cl];
+
+u32 rol_long_asm(u32 *flags,u32 d, u8 s);
+#pragma aux rol_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "rol eax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [cl] \
+ value [eax] \
+ modify exact [eax cl];
+
+u8 ror_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux ror_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "ror al,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [cl] \
+ value [al] \
+ modify exact [al cl];
+
+u16 ror_word_asm(u32 *flags,u16 d, u8 s);
+#pragma aux ror_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "ror ax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [cl] \
+ value [ax] \
+ modify exact [ax cl];
+
+u32 ror_long_asm(u32 *flags,u32 d, u8 s);
+#pragma aux ror_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "ror eax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [cl] \
+ value [eax] \
+ modify exact [eax cl];
+
+u8 shl_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux shl_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "shl al,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [cl] \
+ value [al] \
+ modify exact [al cl];
+
+u16 shl_word_asm(u32 *flags,u16 d, u8 s);
+#pragma aux shl_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "shl ax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [cl] \
+ value [ax] \
+ modify exact [ax cl];
+
+u32 shl_long_asm(u32 *flags,u32 d, u8 s);
+#pragma aux shl_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "shl eax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [cl] \
+ value [eax] \
+ modify exact [eax cl];
+
+u8 shr_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux shr_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "shr al,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [cl] \
+ value [al] \
+ modify exact [al cl];
+
+u16 shr_word_asm(u32 *flags,u16 d, u8 s);
+#pragma aux shr_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "shr ax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [cl] \
+ value [ax] \
+ modify exact [ax cl];
+
+u32 shr_long_asm(u32 *flags,u32 d, u8 s);
+#pragma aux shr_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "shr eax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [cl] \
+ value [eax] \
+ modify exact [eax cl];
+
+u8 sar_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux sar_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "sar al,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [cl] \
+ value [al] \
+ modify exact [al cl];
+
+u16 sar_word_asm(u32 *flags,u16 d, u8 s);
+#pragma aux sar_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "sar ax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [cl] \
+ value [ax] \
+ modify exact [ax cl];
+
+u32 sar_long_asm(u32 *flags,u32 d, u8 s);
+#pragma aux sar_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "sar eax,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [cl] \
+ value [eax] \
+ modify exact [eax cl];
+
+u16 shld_word_asm(u32 *flags,u16 d, u16 fill, u8 s);
+#pragma aux shld_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "shld ax,dx,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [dx] [cl] \
+ value [ax] \
+ modify exact [ax dx cl];
+
+u32 shld_long_asm(u32 *flags,u32 d, u32 fill, u8 s);
+#pragma aux shld_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "shld eax,edx,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [edx] [cl] \
+ value [eax] \
+ modify exact [eax edx cl];
+
+u16 shrd_word_asm(u32 *flags,u16 d, u16 fill, u8 s);
+#pragma aux shrd_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "shrd ax,dx,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [dx] [cl] \
+ value [ax] \
+ modify exact [ax dx cl];
+
+u32 shrd_long_asm(u32 *flags,u32 d, u32 fill, u8 s);
+#pragma aux shrd_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "shrd eax,edx,cl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [edx] [cl] \
+ value [eax] \
+ modify exact [eax edx cl];
+
+u8 sbb_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux sbb_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "sbb al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ value [al] \
+ modify exact [al bl];
+
+u16 sbb_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux sbb_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "sbb ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ value [ax] \
+ modify exact [ax bx];
+
+u32 sbb_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux sbb_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "sbb eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ value [eax] \
+ modify exact [eax ebx];
+
+u8 sub_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux sub_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "sub al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ value [al] \
+ modify exact [al bl];
+
+u16 sub_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux sub_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "sub ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ value [ax] \
+ modify exact [ax bx];
+
+u32 sub_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux sub_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "sub eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ value [eax] \
+ modify exact [eax ebx];
+
+void test_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux test_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "test al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ modify exact [al bl];
+
+void test_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux test_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "test ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ modify exact [ax bx];
+
+void test_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux test_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "test eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ modify exact [eax ebx];
+
+u8 xor_byte_asm(u32 *flags,u8 d, u8 s);
+#pragma aux xor_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "xor al,bl" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [al] [bl] \
+ value [al] \
+ modify exact [al bl];
+
+u16 xor_word_asm(u32 *flags,u16 d, u16 s);
+#pragma aux xor_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "xor ax,bx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [ax] [bx] \
+ value [ax] \
+ modify exact [ax bx];
+
+u32 xor_long_asm(u32 *flags,u32 d, u32 s);
+#pragma aux xor_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "xor eax,ebx" \
+ "pushf" \
+ "pop [edi]" \
+ parm [edi] [eax] [ebx] \
+ value [eax] \
+ modify exact [eax ebx];
+
+void imul_byte_asm(u32 *flags,u16 *ax,u8 d,u8 s);
+#pragma aux imul_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "imul bl" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],ax" \
+ parm [edi] [esi] [al] [bl] \
+ modify exact [esi ax bl];
+
+void imul_word_asm(u32 *flags,u16 *ax,u16 *dx,u16 d,u16 s);
+#pragma aux imul_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "imul bx" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],ax" \
+ "mov [ecx],dx" \
+ parm [edi] [esi] [ecx] [ax] [bx]\
+ modify exact [esi edi ax bx dx];
+
+void imul_long_asm(u32 *flags,u32 *eax,u32 *edx,u32 d,u32 s);
+#pragma aux imul_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "imul ebx" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],eax" \
+ "mov [ecx],edx" \
+ parm [edi] [esi] [ecx] [eax] [ebx] \
+ modify exact [esi edi eax ebx edx];
+
+void mul_byte_asm(u32 *flags,u16 *ax,u8 d,u8 s);
+#pragma aux mul_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "mul bl" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],ax" \
+ parm [edi] [esi] [al] [bl] \
+ modify exact [esi ax bl];
+
+void mul_word_asm(u32 *flags,u16 *ax,u16 *dx,u16 d,u16 s);
+#pragma aux mul_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "mul bx" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],ax" \
+ "mov [ecx],dx" \
+ parm [edi] [esi] [ecx] [ax] [bx]\
+ modify exact [esi edi ax bx dx];
+
+void mul_long_asm(u32 *flags,u32 *eax,u32 *edx,u32 d,u32 s);
+#pragma aux mul_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "mul ebx" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],eax" \
+ "mov [ecx],edx" \
+ parm [edi] [esi] [ecx] [eax] [ebx] \
+ modify exact [esi edi eax ebx edx];
+
+void idiv_byte_asm(u32 *flags,u8 *al,u8 *ah,u16 d,u8 s);
+#pragma aux idiv_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "idiv bl" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],al" \
+ "mov [ecx],ah" \
+ parm [edi] [esi] [ecx] [ax] [bl]\
+ modify exact [esi edi ax bl];
+
+void idiv_word_asm(u32 *flags,u16 *ax,u16 *dx,u16 dlo,u16 dhi,u16 s);
+#pragma aux idiv_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "idiv bx" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],ax" \
+ "mov [ecx],dx" \
+ parm [edi] [esi] [ecx] [ax] [dx] [bx]\
+ modify exact [esi edi ax dx bx];
+
+void idiv_long_asm(u32 *flags,u32 *eax,u32 *edx,u32 dlo,u32 dhi,u32 s);
+#pragma aux idiv_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "idiv ebx" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],eax" \
+ "mov [ecx],edx" \
+ parm [edi] [esi] [ecx] [eax] [edx] [ebx]\
+ modify exact [esi edi eax edx ebx];
+
+void div_byte_asm(u32 *flags,u8 *al,u8 *ah,u16 d,u8 s);
+#pragma aux div_byte_asm = \
+ "push [edi]" \
+ "popf" \
+ "div bl" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],al" \
+ "mov [ecx],ah" \
+ parm [edi] [esi] [ecx] [ax] [bl]\
+ modify exact [esi edi ax bl];
+
+void div_word_asm(u32 *flags,u16 *ax,u16 *dx,u16 dlo,u16 dhi,u16 s);
+#pragma aux div_word_asm = \
+ "push [edi]" \
+ "popf" \
+ "div bx" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],ax" \
+ "mov [ecx],dx" \
+ parm [edi] [esi] [ecx] [ax] [dx] [bx]\
+ modify exact [esi edi ax dx bx];
+
+void div_long_asm(u32 *flags,u32 *eax,u32 *edx,u32 dlo,u32 dhi,u32 s);
+#pragma aux div_long_asm = \
+ "push [edi]" \
+ "popf" \
+ "div ebx" \
+ "pushf" \
+ "pop [edi]" \
+ "mov [esi],eax" \
+ "mov [ecx],edx" \
+ parm [edi] [esi] [ecx] [eax] [edx] [ebx]\
+ modify exact [esi edi eax edx ebx];
+
+#endif
+
+#endif /* __X86EMU_PRIM_ASM_H */
diff --git a/cfe/cfe/x86emu/x86emu/prim_ops.h b/cfe/cfe/x86emu/x86emu/prim_ops.h
new file mode 100644
index 0000000..1633fe1
--- /dev/null
+++ b/cfe/cfe/x86emu/x86emu/prim_ops.h
@@ -0,0 +1,231 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for primitive operation functions.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_PRIM_OPS_H
+#define __X86EMU_PRIM_OPS_H
+
+#include "x86emu/prim_asm.h"
+
+#ifdef __cplusplus
+extern "C" { /* Use "C" linkage when in C++ mode */
+#endif
+
+u16 aaa_word (u16 d);
+u16 aas_word (u16 d);
+u16 aad_word (u16 d);
+u16 aam_word (u8 d);
+u8 adc_byte (u8 d, u8 s);
+u16 adc_word (u16 d, u16 s);
+u32 adc_long (u32 d, u32 s);
+u8 add_byte (u8 d, u8 s);
+u16 add_word (u16 d, u16 s);
+u32 add_long (u32 d, u32 s);
+u8 and_byte (u8 d, u8 s);
+u16 and_word (u16 d, u16 s);
+u32 and_long (u32 d, u32 s);
+u8 cmp_byte (u8 d, u8 s);
+u16 cmp_word (u16 d, u16 s);
+u32 cmp_long (u32 d, u32 s);
+u8 daa_byte (u8 d);
+u8 das_byte (u8 d);
+u8 dec_byte (u8 d);
+u16 dec_word (u16 d);
+u32 dec_long (u32 d);
+u8 inc_byte (u8 d);
+u16 inc_word (u16 d);
+u32 inc_long (u32 d);
+u8 or_byte (u8 d, u8 s);
+u16 or_word (u16 d, u16 s);
+u32 or_long (u32 d, u32 s);
+u8 neg_byte (u8 s);
+u16 neg_word (u16 s);
+u32 neg_long (u32 s);
+u8 not_byte (u8 s);
+u16 not_word (u16 s);
+u32 not_long (u32 s);
+u8 rcl_byte (u8 d, u8 s);
+u16 rcl_word (u16 d, u8 s);
+u32 rcl_long (u32 d, u8 s);
+u8 rcr_byte (u8 d, u8 s);
+u16 rcr_word (u16 d, u8 s);
+u32 rcr_long (u32 d, u8 s);
+u8 rol_byte (u8 d, u8 s);
+u16 rol_word (u16 d, u8 s);
+u32 rol_long (u32 d, u8 s);
+u8 ror_byte (u8 d, u8 s);
+u16 ror_word (u16 d, u8 s);
+u32 ror_long (u32 d, u8 s);
+u8 shl_byte (u8 d, u8 s);
+u16 shl_word (u16 d, u8 s);
+u32 shl_long (u32 d, u8 s);
+u8 shr_byte (u8 d, u8 s);
+u16 shr_word (u16 d, u8 s);
+u32 shr_long (u32 d, u8 s);
+u8 sar_byte (u8 d, u8 s);
+u16 sar_word (u16 d, u8 s);
+u32 sar_long (u32 d, u8 s);
+u16 shld_word (u16 d, u16 fill, u8 s);
+u32 shld_long (u32 d, u32 fill, u8 s);
+u16 shrd_word (u16 d, u16 fill, u8 s);
+u32 shrd_long (u32 d, u32 fill, u8 s);
+u8 sbb_byte (u8 d, u8 s);
+u16 sbb_word (u16 d, u16 s);
+u32 sbb_long (u32 d, u32 s);
+u8 sub_byte (u8 d, u8 s);
+u16 sub_word (u16 d, u16 s);
+u32 sub_long (u32 d, u32 s);
+void test_byte (u8 d, u8 s);
+void test_word (u16 d, u16 s);
+void test_long (u32 d, u32 s);
+u8 xor_byte (u8 d, u8 s);
+u16 xor_word (u16 d, u16 s);
+u32 xor_long (u32 d, u32 s);
+void imul_byte (u8 s);
+void imul_word (u16 s);
+void imul_long (u32 s);
+void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s);
+void mul_byte (u8 s);
+void mul_word (u16 s);
+void mul_long (u32 s);
+void idiv_byte (u8 s);
+void idiv_word (u16 s);
+void idiv_long (u32 s);
+void div_byte (u8 s);
+void div_word (u16 s);
+void div_long (u32 s);
+void ins (int size);
+void outs (int size);
+u16 mem_access_word (int addr);
+void push_word (u16 w);
+void push_long (u32 w);
+u16 pop_word (void);
+u32 pop_long (void);
+
+#if defined(__HAVE_INLINE_ASSEMBLER__) && !defined(PRIM_OPS_NO_REDEFINE_ASM)
+
+#define aaa_word(d) aaa_word_asm(&M.x86.R_EFLG,d)
+#define aas_word(d) aas_word_asm(&M.x86.R_EFLG,d)
+#define aad_word(d) aad_word_asm(&M.x86.R_EFLG,d)
+#define aam_word(d) aam_word_asm(&M.x86.R_EFLG,d)
+#define adc_byte(d,s) adc_byte_asm(&M.x86.R_EFLG,d,s)
+#define adc_word(d,s) adc_word_asm(&M.x86.R_EFLG,d,s)
+#define adc_long(d,s) adc_long_asm(&M.x86.R_EFLG,d,s)
+#define add_byte(d,s) add_byte_asm(&M.x86.R_EFLG,d,s)
+#define add_word(d,s) add_word_asm(&M.x86.R_EFLG,d,s)
+#define add_long(d,s) add_long_asm(&M.x86.R_EFLG,d,s)
+#define and_byte(d,s) and_byte_asm(&M.x86.R_EFLG,d,s)
+#define and_word(d,s) and_word_asm(&M.x86.R_EFLG,d,s)
+#define and_long(d,s) and_long_asm(&M.x86.R_EFLG,d,s)
+#define cmp_byte(d,s) cmp_byte_asm(&M.x86.R_EFLG,d,s)
+#define cmp_word(d,s) cmp_word_asm(&M.x86.R_EFLG,d,s)
+#define cmp_long(d,s) cmp_long_asm(&M.x86.R_EFLG,d,s)
+#define daa_byte(d) daa_byte_asm(&M.x86.R_EFLG,d)
+#define das_byte(d) das_byte_asm(&M.x86.R_EFLG,d)
+#define dec_byte(d) dec_byte_asm(&M.x86.R_EFLG,d)
+#define dec_word(d) dec_word_asm(&M.x86.R_EFLG,d)
+#define dec_long(d) dec_long_asm(&M.x86.R_EFLG,d)
+#define inc_byte(d) inc_byte_asm(&M.x86.R_EFLG,d)
+#define inc_word(d) inc_word_asm(&M.x86.R_EFLG,d)
+#define inc_long(d) inc_long_asm(&M.x86.R_EFLG,d)
+#define or_byte(d,s) or_byte_asm(&M.x86.R_EFLG,d,s)
+#define or_word(d,s) or_word_asm(&M.x86.R_EFLG,d,s)
+#define or_long(d,s) or_long_asm(&M.x86.R_EFLG,d,s)
+#define neg_byte(s) neg_byte_asm(&M.x86.R_EFLG,s)
+#define neg_word(s) neg_word_asm(&M.x86.R_EFLG,s)
+#define neg_long(s) neg_long_asm(&M.x86.R_EFLG,s)
+#define not_byte(s) not_byte_asm(&M.x86.R_EFLG,s)
+#define not_word(s) not_word_asm(&M.x86.R_EFLG,s)
+#define not_long(s) not_long_asm(&M.x86.R_EFLG,s)
+#define rcl_byte(d,s) rcl_byte_asm(&M.x86.R_EFLG,d,s)
+#define rcl_word(d,s) rcl_word_asm(&M.x86.R_EFLG,d,s)
+#define rcl_long(d,s) rcl_long_asm(&M.x86.R_EFLG,d,s)
+#define rcr_byte(d,s) rcr_byte_asm(&M.x86.R_EFLG,d,s)
+#define rcr_word(d,s) rcr_word_asm(&M.x86.R_EFLG,d,s)
+#define rcr_long(d,s) rcr_long_asm(&M.x86.R_EFLG,d,s)
+#define rol_byte(d,s) rol_byte_asm(&M.x86.R_EFLG,d,s)
+#define rol_word(d,s) rol_word_asm(&M.x86.R_EFLG,d,s)
+#define rol_long(d,s) rol_long_asm(&M.x86.R_EFLG,d,s)
+#define ror_byte(d,s) ror_byte_asm(&M.x86.R_EFLG,d,s)
+#define ror_word(d,s) ror_word_asm(&M.x86.R_EFLG,d,s)
+#define ror_long(d,s) ror_long_asm(&M.x86.R_EFLG,d,s)
+#define shl_byte(d,s) shl_byte_asm(&M.x86.R_EFLG,d,s)
+#define shl_word(d,s) shl_word_asm(&M.x86.R_EFLG,d,s)
+#define shl_long(d,s) shl_long_asm(&M.x86.R_EFLG,d,s)
+#define shr_byte(d,s) shr_byte_asm(&M.x86.R_EFLG,d,s)
+#define shr_word(d,s) shr_word_asm(&M.x86.R_EFLG,d,s)
+#define shr_long(d,s) shr_long_asm(&M.x86.R_EFLG,d,s)
+#define sar_byte(d,s) sar_byte_asm(&M.x86.R_EFLG,d,s)
+#define sar_word(d,s) sar_word_asm(&M.x86.R_EFLG,d,s)
+#define sar_long(d,s) sar_long_asm(&M.x86.R_EFLG,d,s)
+#define shld_word(d,fill,s) shld_word_asm(&M.x86.R_EFLG,d,fill,s)
+#define shld_long(d,fill,s) shld_long_asm(&M.x86.R_EFLG,d,fill,s)
+#define shrd_word(d,fill,s) shrd_word_asm(&M.x86.R_EFLG,d,fill,s)
+#define shrd_long(d,fill,s) shrd_long_asm(&M.x86.R_EFLG,d,fill,s)
+#define sbb_byte(d,s) sbb_byte_asm(&M.x86.R_EFLG,d,s)
+#define sbb_word(d,s) sbb_word_asm(&M.x86.R_EFLG,d,s)
+#define sbb_long(d,s) sbb_long_asm(&M.x86.R_EFLG,d,s)
+#define sub_byte(d,s) sub_byte_asm(&M.x86.R_EFLG,d,s)
+#define sub_word(d,s) sub_word_asm(&M.x86.R_EFLG,d,s)
+#define sub_long(d,s) sub_long_asm(&M.x86.R_EFLG,d,s)
+#define test_byte(d,s) test_byte_asm(&M.x86.R_EFLG,d,s)
+#define test_word(d,s) test_word_asm(&M.x86.R_EFLG,d,s)
+#define test_long(d,s) test_long_asm(&M.x86.R_EFLG,d,s)
+#define xor_byte(d,s) xor_byte_asm(&M.x86.R_EFLG,d,s)
+#define xor_word(d,s) xor_word_asm(&M.x86.R_EFLG,d,s)
+#define xor_long(d,s) xor_long_asm(&M.x86.R_EFLG,d,s)
+#define imul_byte(s) imul_byte_asm(&M.x86.R_EFLG,&M.x86.R_AX,M.x86.R_AL,s)
+#define imul_word(s) imul_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,s)
+#define imul_long(s) imul_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s)
+#define imul_long_direct(res_lo,res_hi,d,s) imul_long_asm(&M.x86.R_EFLG,res_lo,res_hi,d,s)
+#define mul_byte(s) mul_byte_asm(&M.x86.R_EFLG,&M.x86.R_AX,M.x86.R_AL,s)
+#define mul_word(s) mul_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,s)
+#define mul_long(s) mul_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s)
+#define idiv_byte(s) idiv_byte_asm(&M.x86.R_EFLG,&M.x86.R_AL,&M.x86.R_AH,M.x86.R_AX,s)
+#define idiv_word(s) idiv_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,M.x86.R_DX,s)
+#define idiv_long(s) idiv_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,M.x86.R_EDX,s)
+#define div_byte(s) div_byte_asm(&M.x86.R_EFLG,&M.x86.R_AL,&M.x86.R_AH,M.x86.R_AX,s)
+#define div_word(s) div_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,M.x86.R_DX,s)
+#define div_long(s) div_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,M.x86.R_EDX,s)
+
+#endif
+
+#ifdef __cplusplus
+} /* End of "C" linkage for C++ */
+#endif
+
+#endif /* __X86EMU_PRIM_OPS_H */
diff --git a/cfe/cfe/x86emu/x86emu/regs.h b/cfe/cfe/x86emu/x86emu/regs.h
new file mode 100644
index 0000000..b0a6231
--- /dev/null
+++ b/cfe/cfe/x86emu/x86emu/regs.h
@@ -0,0 +1,351 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for x86 register definitions.
+*
+****************************************************************************/
+
+#ifndef __X86EMU_REGS_H
+#define __X86EMU_REGS_H
+
+#ifdef __mips
+#if defined(__MIPSEB)
+#define __BIG_ENDIAN__
+#elif defined(__MIPSEL)
+#define __LITTLE_ENDIAN__
+#else
+#error "You must define either __MIPSEB or __MIPSEL"
+#endif
+#endif
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+#ifndef __mips
+#pragma pack(1)
+#endif
+
+/*
+ * General EAX, EBX, ECX, EDX type registers. Note that for
+ * portability, and speed, the issue of byte swapping is not addressed
+ * in the registers. All registers are stored in the default format
+ * available on the host machine. The only critical issue is that the
+ * registers should line up EXACTLY in the same manner as they do in
+ * the 386. That is:
+ *
+ * EAX & 0xff === AL
+ * EAX & 0xffff == AX
+ *
+ * etc. The result is that alot of the calculations can then be
+ * done using the native instruction set fully.
+ */
+
+#ifdef __BIG_ENDIAN__
+
+typedef struct {
+ u32 e_reg;
+ } I32_reg_t;
+
+typedef struct {
+ u16 filler0, x_reg;
+ } I16_reg_t;
+
+typedef struct {
+ u8 filler0, filler1, h_reg, l_reg;
+ } I8_reg_t;
+
+#else /* !__BIG_ENDIAN__ */
+
+typedef struct {
+ u32 e_reg;
+ } I32_reg_t;
+
+typedef struct {
+ u16 x_reg;
+ } I16_reg_t;
+
+typedef struct {
+ u8 l_reg, h_reg;
+ } I8_reg_t;
+
+#endif /* BIG_ENDIAN */
+
+typedef union {
+ I32_reg_t I32_reg;
+ I16_reg_t I16_reg;
+ I8_reg_t I8_reg;
+ } i386_general_register;
+
+struct i386_general_regs {
+ i386_general_register A, B, C, D;
+ };
+
+typedef struct i386_general_regs Gen_reg_t;
+
+struct i386_special_regs {
+ i386_general_register SP, BP, SI, DI, IP;
+ u32 FLAGS;
+ };
+
+/*
+ * Segment registers here represent the 16 bit quantities
+ * CS, DS, ES, SS.
+ */
+
+struct i386_segment_regs {
+ u16 CS, DS, SS, ES, FS, GS;
+ };
+
+/* 8 bit registers */
+#define R_AH gen.A.I8_reg.h_reg
+#define R_AL gen.A.I8_reg.l_reg
+#define R_BH gen.B.I8_reg.h_reg
+#define R_BL gen.B.I8_reg.l_reg
+#define R_CH gen.C.I8_reg.h_reg
+#define R_CL gen.C.I8_reg.l_reg
+#define R_DH gen.D.I8_reg.h_reg
+#define R_DL gen.D.I8_reg.l_reg
+
+/* 16 bit registers */
+#define R_AX gen.A.I16_reg.x_reg
+#define R_BX gen.B.I16_reg.x_reg
+#define R_CX gen.C.I16_reg.x_reg
+#define R_DX gen.D.I16_reg.x_reg
+
+/* 32 bit extended registers */
+#define R_EAX gen.A.I32_reg.e_reg
+#define R_EBX gen.B.I32_reg.e_reg
+#define R_ECX gen.C.I32_reg.e_reg
+#define R_EDX gen.D.I32_reg.e_reg
+
+/* special registers */
+#define R_SP spc.SP.I16_reg.x_reg
+#define R_BP spc.BP.I16_reg.x_reg
+#define R_SI spc.SI.I16_reg.x_reg
+#define R_DI spc.DI.I16_reg.x_reg
+#define R_IP spc.IP.I16_reg.x_reg
+#define R_FLG spc.FLAGS
+
+/* special registers */
+#define R_SP spc.SP.I16_reg.x_reg
+#define R_BP spc.BP.I16_reg.x_reg
+#define R_SI spc.SI.I16_reg.x_reg
+#define R_DI spc.DI.I16_reg.x_reg
+#define R_IP spc.IP.I16_reg.x_reg
+#define R_FLG spc.FLAGS
+
+/* special registers */
+#define R_ESP spc.SP.I32_reg.e_reg
+#define R_EBP spc.BP.I32_reg.e_reg
+#define R_ESI spc.SI.I32_reg.e_reg
+#define R_EDI spc.DI.I32_reg.e_reg
+#define R_EIP spc.IP.I32_reg.e_reg
+#define R_EFLG spc.FLAGS
+
+/* segment registers */
+#define R_CS seg.CS
+#define R_DS seg.DS
+#define R_SS seg.SS
+#define R_ES seg.ES
+#define R_FS seg.FS
+#define R_GS seg.GS
+
+/* flag conditions */
+#define FB_CF 0x0001 /* CARRY flag */
+#define FB_PF 0x0004 /* PARITY flag */
+#define FB_AF 0x0010 /* AUX flag */
+#define FB_ZF 0x0040 /* ZERO flag */
+#define FB_SF 0x0080 /* SIGN flag */
+#define FB_TF 0x0100 /* TRAP flag */
+#define FB_IF 0x0200 /* INTERRUPT ENABLE flag */
+#define FB_DF 0x0400 /* DIR flag */
+#define FB_OF 0x0800 /* OVERFLOW flag */
+
+/* 80286 and above always have bit#1 set */
+#define F_ALWAYS_ON (0x0002) /* flag bits always on */
+
+/*
+ * Define a mask for only those flag bits we will ever pass back
+ * (via PUSHF)
+ */
+#define F_MSK (FB_CF|FB_PF|FB_AF|FB_ZF|FB_SF|FB_TF|FB_IF|FB_DF|FB_OF)
+
+/* following bits masked in to a 16bit quantity */
+
+#define F_CF 0x0001 /* CARRY flag */
+#define F_PF 0x0004 /* PARITY flag */
+#define F_AF 0x0010 /* AUX flag */
+#define F_ZF 0x0040 /* ZERO flag */
+#define F_SF 0x0080 /* SIGN flag */
+#define F_TF 0x0100 /* TRAP flag */
+#define F_IF 0x0200 /* INTERRUPT ENABLE flag */
+#define F_DF 0x0400 /* DIR flag */
+#define F_OF 0x0800 /* OVERFLOW flag */
+
+#define TOGGLE_FLAG(flag) (M.x86.R_FLG ^= (flag))
+#define SET_FLAG(flag) (M.x86.R_FLG |= (flag))
+#define CLEAR_FLAG(flag) (M.x86.R_FLG &= ~(flag))
+#define ACCESS_FLAG(flag) (M.x86.R_FLG & (flag))
+#define CLEARALL_FLAG(m) (M.x86.R_FLG = 0)
+
+#define CONDITIONAL_SET_FLAG(COND,FLAG) \
+ if (COND) SET_FLAG(FLAG); else CLEAR_FLAG(FLAG)
+
+#define F_PF_CALC 0x010000 /* PARITY flag has been calced */
+#define F_ZF_CALC 0x020000 /* ZERO flag has been calced */
+#define F_SF_CALC 0x040000 /* SIGN flag has been calced */
+
+#define F_ALL_CALC 0xff0000 /* All have been calced */
+
+/*
+ * Emulator machine state.
+ * Segment usage control.
+ */
+#define SYSMODE_SEG_DS_SS 0x00000001
+#define SYSMODE_SEGOVR_CS 0x00000002
+#define SYSMODE_SEGOVR_DS 0x00000004
+#define SYSMODE_SEGOVR_ES 0x00000008
+#define SYSMODE_SEGOVR_FS 0x00000010
+#define SYSMODE_SEGOVR_GS 0x00000020
+#define SYSMODE_SEGOVR_SS 0x00000040
+#define SYSMODE_PREFIX_REPE 0x00000080
+#define SYSMODE_PREFIX_REPNE 0x00000100
+#define SYSMODE_PREFIX_DATA 0x00000200
+#define SYSMODE_PREFIX_ADDR 0x00000400
+#define SYSMODE_INTR_PENDING 0x10000000
+#define SYSMODE_EXTRN_INTR 0x20000000
+#define SYSMODE_HALTED 0x40000000
+
+#define SYSMODE_SEGMASK (SYSMODE_SEG_DS_SS | \
+ SYSMODE_SEGOVR_CS | \
+ SYSMODE_SEGOVR_DS | \
+ SYSMODE_SEGOVR_ES | \
+ SYSMODE_SEGOVR_FS | \
+ SYSMODE_SEGOVR_GS | \
+ SYSMODE_SEGOVR_SS)
+#define SYSMODE_CLRMASK (SYSMODE_SEG_DS_SS | \
+ SYSMODE_SEGOVR_CS | \
+ SYSMODE_SEGOVR_DS | \
+ SYSMODE_SEGOVR_ES | \
+ SYSMODE_SEGOVR_FS | \
+ SYSMODE_SEGOVR_GS | \
+ SYSMODE_SEGOVR_SS | \
+ SYSMODE_PREFIX_DATA | \
+ SYSMODE_PREFIX_ADDR)
+
+#define INTR_SYNCH 0x1
+#define INTR_ASYNCH 0x2
+#define INTR_HALTED 0x4
+
+typedef struct {
+ struct i386_general_regs gen;
+ struct i386_special_regs spc;
+ struct i386_segment_regs seg;
+ /*
+ * MODE contains information on:
+ * REPE prefix 2 bits repe,repne
+ * SEGMENT overrides 5 bits normal,DS,SS,CS,ES
+ * Delayed flag set 3 bits (zero, signed, parity)
+ * reserved 6 bits
+ * interrupt # 8 bits instruction raised interrupt
+ * BIOS video segregs 4 bits
+ * Interrupt Pending 1 bits
+ * Extern interrupt 1 bits
+ * Halted 1 bits
+ */
+ long mode;
+ u8 intno;
+ volatile int intr; /* mask of pending interrupts */
+ int debug;
+#ifdef DEBUG
+ int check;
+ u16 saved_ip;
+ u16 saved_cs;
+ int enc_pos;
+ int enc_str_pos;
+ char decode_buf[32]; /* encoded byte stream */
+ char decoded_buf[256]; /* disassembled strings */
+#endif
+ } X86EMU_regs;
+
+/****************************************************************************
+REMARKS:
+Structure maintaining the emulator machine state.
+
+MEMBERS:
+x86 - X86 registers
+mem_base - Base real mode memory for the emulator
+mem_size - Size of the real mode memory block for the emulator
+****************************************************************************/
+typedef struct {
+ X86EMU_regs x86;
+ unsigned long mem_base;
+ unsigned long mem_size;
+ void* private;
+ } X86EMU_sysEnv;
+
+#ifndef __mips
+#pragma pack()
+#endif
+
+/*----------------------------- Global Variables --------------------------*/
+
+#ifdef __cplusplus
+extern "C" { /* Use "C" linkage when in C++ mode */
+#endif
+
+/* Global emulator machine state.
+ *
+ * We keep it global to avoid pointer dereferences in the code for speed.
+ */
+
+extern X86EMU_sysEnv _X86EMU_env;
+#define M _X86EMU_env
+
+/*-------------------------- Function Prototypes --------------------------*/
+
+/* Function to log information at runtime */
+
+#ifdef _CFE_
+#include "lib_printf.h"
+#define printk xprintf
+#define sprintf xsprintf
+#else
+void printk(const char *fmt, ...);
+#endif
+
+#ifdef __cplusplus
+} /* End of "C" linkage for C++ */
+#endif
+
+#endif /* __X86EMU_REGS_H */
diff --git a/cfe/cfe/x86emu/x86emu/types.h b/cfe/cfe/x86emu/x86emu/types.h
new file mode 100644
index 0000000..f3d3783
--- /dev/null
+++ b/cfe/cfe/x86emu/x86emu/types.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for x86 emulator type definitions.
+*
+****************************************************************************/
+
+/* $XFree86: xc/extras/x86emu/include/x86emu/types.h,v 1.4 2000/09/26 15:56:44 tsi Exp $ */
+
+#ifndef __X86EMU_TYPES_H
+#define __X86EMU_TYPES_H
+
+#ifndef IN_MODULE
+//#include <sys/types.h>
+#endif
+
+/*
+ * The following kludge is an attempt to work around typedef conflicts with
+ * <sys/types.h>.
+ */
+#define u8 x86emuu8
+#define u16 x86emuu16
+#define u32 x86emuu32
+#define u64 x86emuu64
+#define s8 x86emus8
+#define s16 x86emus16
+#define s32 x86emus32
+#define s64 x86emus64
+#define uint x86emuuint
+#define sint x86emusint
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+/* Currently only for Linux/32bit */
+#if defined(__GNUC__) && !defined(NO_LONG_LONG)
+#define __HAS_LONG_LONG__
+#endif
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+#ifdef __HAS_LONG_LONG__
+typedef unsigned long long u64;
+#endif
+
+typedef char s8;
+typedef short s16;
+typedef int s32;
+#ifdef __HAS_LONG_LONG__
+typedef long long s64;
+#endif
+
+typedef unsigned int uint;
+typedef int sint;
+
+typedef u16 X86EMU_pioAddr;
+
+#endif /* __X86EMU_TYPES_H */
diff --git a/cfe/cfe/x86emu/x86emu/x86emui.h b/cfe/cfe/x86emu/x86emu/x86emui.h
new file mode 100644
index 0000000..594b344
--- /dev/null
+++ b/cfe/cfe/x86emu/x86emu/x86emui.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+*
+* Realmode X86 Emulator Library
+*
+* Copyright (C) 1996-1999 SciTech Software, Inc.
+* Copyright (C) David Mosberger-Tang
+* Copyright (C) 1999 Egbert Eich
+*
+* ========================================================================
+*
+* Permission to use, copy, modify, distribute, and sell this software and
+* its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies and that
+* both that copyright notice and this permission notice appear in
+* supporting documentation, and that the name of the authors not be used
+* in advertising or publicity pertaining to distribution of the software
+* without specific, written prior permission. The authors makes no
+* representations about the suitability of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*
+* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+* PERFORMANCE OF THIS SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+* Developer: Kendall Bennett
+*
+* Description: Header file for system specific functions. These functions
+* are always compiled and linked in the OS depedent libraries,
+* and never in a binary portable driver.
+*
+****************************************************************************/
+
+/* $XFree86: xc/extras/x86emu/src/x86emu/x86emu/x86emui.h,v 1.3 2000/04/17 16:29:47 eich Exp $ */
+
+#ifndef __X86EMU_X86EMUI_H
+#define __X86EMU_X86EMUI_H
+
+/* If we are compiling in C++ mode, we can compile some functions as
+ * inline to increase performance (however the code size increases quite
+ * dramatically in this case).
+ */
+
+#if defined(__cplusplus) && !defined(_NO_INLINE)
+#define _INLINE inline
+#else
+#define _INLINE static
+#endif
+
+/* Get rid of unused parameters in C++ compilation mode */
+
+#ifdef __cplusplus
+#define X86EMU_UNUSED(v)
+#else
+#define X86EMU_UNUSED(v) v
+#endif
+
+#include "x86emu.h"
+#include "x86emu/regs.h"
+#include "x86emu/debug.h"
+#include "x86emu/decode.h"
+#include "x86emu/ops.h"
+#include "x86emu/prim_ops.h"
+#include "x86emu/fpu.h"
+#include "x86emu/fpu_regs.h"
+
+#ifdef IN_MODULE
+#include <xf86_ansic.h>
+#else
+#ifdef _CFE_
+#include "lib_types.h"
+#include "lib_string.h"
+#else
+#include <stdio.h>
+#include <string.h>
+#endif
+#endif
+/*--------------------------- Inline Functions ----------------------------*/
+
+#ifdef __cplusplus
+extern "C" { /* Use "C" linkage when in C++ mode */
+#endif
+
+extern u8 (X86APIP sys_rdb)(u32 addr);
+extern u16 (X86APIP sys_rdw)(u32 addr);
+extern u32 (X86APIP sys_rdl)(u32 addr);
+extern void (X86APIP sys_wrb)(u32 addr,u8 val);
+extern void (X86APIP sys_wrw)(u32 addr,u16 val);
+extern void (X86APIP sys_wrl)(u32 addr,u32 val);
+
+extern u8 (X86APIP sys_inb)(X86EMU_pioAddr addr);
+extern u16 (X86APIP sys_inw)(X86EMU_pioAddr addr);
+extern u32 (X86APIP sys_inl)(X86EMU_pioAddr addr);
+extern void (X86APIP sys_outb)(X86EMU_pioAddr addr,u8 val);
+extern void (X86APIP sys_outw)(X86EMU_pioAddr addr,u16 val);
+extern void (X86APIP sys_outl)(X86EMU_pioAddr addr,u32 val);
+
+#ifdef __cplusplus
+} /* End of "C" linkage for C++ */
+#endif
+
+#endif /* __X86EMU_X86EMUI_H */
diff --git a/cfe/cfe/zlib/ChangeLog b/cfe/cfe/zlib/ChangeLog
new file mode 100644
index 0000000..567a500
--- /dev/null
+++ b/cfe/cfe/zlib/ChangeLog
@@ -0,0 +1,471 @@
+
+ ChangeLog file for zlib
+
+Changes in 1.1.3 (9 July 1998)
+- fix "an inflate input buffer bug that shows up on rare but persistent
+ occasions" (Mark)
+- fix gzread and gztell for concatenated .gz files (Didier Le Botlan)
+- fix gzseek(..., SEEK_SET) in write mode
+- fix crc check after a gzeek (Frank Faubert)
+- fix miniunzip when the last entry in a zip file is itself a zip file
+ (J Lillge)
+- add contrib/asm586 and contrib/asm686 (Brian Raiter)
+ See http://www.muppetlabs.com/~breadbox/software/assembly.html
+- add support for Delphi 3 in contrib/delphi (Bob Dellaca)
+- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti)
+- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren)
+- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks)
+- added a FAQ file
+
+- Support gzdopen on Mac with Metrowerks (Jason Linhart)
+- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart)
+- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young)
+- avoid some warnings with Borland C (Tom Tanner)
+- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant)
+- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant)
+- allow several arguments to configure (Tim Mooney, Frodo Looijaard)
+- use libdir and includedir in Makefile.in (Tim Mooney)
+- support shared libraries on OSF1 V4 (Tim Mooney)
+- remove so_locations in "make clean" (Tim Mooney)
+- fix maketree.c compilation error (Glenn, Mark)
+- Python interface to zlib now in Python 1.5 (Jeremy Hylton)
+- new Makefile.riscos (Rich Walker)
+- initialize static descriptors in trees.c for embedded targets (Nick Smith)
+- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith)
+- add the OS/2 files in Makefile.in too (Andrew Zabolotny)
+- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane)
+- fix maketree.c to allow clean compilation of inffixed.h (Mark)
+- fix parameter check in deflateCopy (Gunther Nikl)
+- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler)
+- Many portability patches by Christian Spieler:
+ . zutil.c, zutil.h: added "const" for zmem*
+ . Make_vms.com: fixed some typos
+ . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists
+ . msdos/Makefile.msc: remove "default rtl link library" info from obj files
+ . msdos/Makefile.*: use model-dependent name for the built zlib library
+ . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc:
+ new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT)
+- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane)
+- replace __far with _far for better portability (Christian Spieler, Tom Lane)
+- fix test for errno.h in configure (Tim Newsham)
+
+Changes in 1.1.2 (19 March 98)
+- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant)
+ See http://www.winimage.com/zLibDll/unzip.html
+- preinitialize the inflate tables for fixed codes, to make the code
+ completely thread safe (Mark)
+- some simplifications and slight speed-up to the inflate code (Mark)
+- fix gzeof on non-compressed files (Allan Schrum)
+- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs)
+- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn)
+- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny)
+- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori)
+- do not wrap extern "C" around system includes (Tom Lane)
+- mention zlib binding for TCL in README (Andreas Kupries)
+- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert)
+- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson)
+- allow "configure --prefix $HOME" (Tim Mooney)
+- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson)
+- move Makefile.sas to amiga/Makefile.sas
+
+Changes in 1.1.1 (27 Feb 98)
+- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson)
+- remove block truncation heuristic which had very marginal effect for zlib
+ (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the
+ compression ratio on some files. This also allows inlining _tr_tally for
+ matches in deflate_slow.
+- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier)
+
+Changes in 1.1.0 (24 Feb 98)
+- do not return STREAM_END prematurely in inflate (John Bowler)
+- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler)
+- compile with -DFASTEST to get compression code optimized for speed only
+- in minigzip, try mmap'ing the input file first (Miguel Albrecht)
+- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain
+ on Sun but significant on HP)
+
+- add a pointer to experimental unzip library in README (Gilles Vollant)
+- initialize variable gcc in configure (Chris Herborth)
+
+Changes in 1.0.9 (17 Feb 1998)
+- added gzputs and gzgets functions
+- do not clear eof flag in gzseek (Mark Diekhans)
+- fix gzseek for files in transparent mode (Mark Diekhans)
+- do not assume that vsprintf returns the number of bytes written (Jens Krinke)
+- replace EXPORT with ZEXPORT to avoid conflict with other programs
+- added compress2 in zconf.h, zlib.def, zlib.dnt
+- new asm code from Gilles Vollant in contrib/asm386
+- simplify the inflate code (Mark):
+ . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new()
+ . ZALLOC the length list in inflate_trees_fixed() instead of using stack
+ . ZALLOC the value area for huft_build() instead of using stack
+ . Simplify Z_FINISH check in inflate()
+
+- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8
+- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi)
+- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with
+ the declaration of FAR (Gilles VOllant)
+- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann)
+- read_buf buf parameter of type Bytef* instead of charf*
+- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout)
+- do not redeclare unlink in minigzip.c for WIN32 (John Bowler)
+- fix check for presence of directories in "make install" (Ian Willis)
+
+Changes in 1.0.8 (27 Jan 1998)
+- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant)
+- fix gzgetc and gzputc for big endian systems (Markus Oberhumer)
+- added compress2() to allow setting the compression level
+- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong)
+- use constant arrays for the static trees in trees.c instead of computing
+ them at run time (thanks to Ken Raeburn for this suggestion). To create
+ trees.h, compile with GEN_TREES_H and run "make test".
+- check return code of example in "make test" and display result
+- pass minigzip command line options to file_compress
+- simplifying code of inflateSync to avoid gcc 2.8 bug
+
+- support CC="gcc -Wall" in configure -s (QingLong)
+- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn)
+- fix test for shared library support to avoid compiler warnings
+- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant)
+- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit)
+- do not use fdopen for Metrowerks on Mac (Brad Pettit))
+- add checks for gzputc and gzputc in example.c
+- avoid warnings in gzio.c and deflate.c (Andreas Kleinert)
+- use const for the CRC table (Ken Raeburn)
+- fixed "make uninstall" for shared libraries
+- use Tracev instead of Trace in infblock.c
+- in example.c use correct compressed length for test_sync
+- suppress +vnocompatwarnings in configure for HPUX (not always supported)
+
+Changes in 1.0.7 (20 Jan 1998)
+- fix gzseek which was broken in write mode
+- return error for gzseek to negative absolute position
+- fix configure for Linux (Chun-Chung Chen)
+- increase stack space for MSC (Tim Wegner)
+- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant)
+- define EXPORTVA for gzprintf (Gilles Vollant)
+- added man page zlib.3 (Rick Rodgers)
+- for contrib/untgz, fix makedir() and improve Makefile
+
+- check gzseek in write mode in example.c
+- allocate extra buffer for seeks only if gzseek is actually called
+- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant)
+- add inflateSyncPoint in zconf.h
+- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def
+
+Changes in 1.0.6 (19 Jan 1998)
+- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
+ gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
+- Fix a deflate bug occuring only with compression level 0 (thanks to
+ Andy Buckler for finding this one).
+- In minigzip, pass transparently also the first byte for .Z files.
+- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()
+- check Z_FINISH in inflate (thanks to Marc Schluper)
+- Implement deflateCopy (thanks to Adam Costello)
+- make static libraries by default in configure, add --shared option.
+- move MSDOS or Windows specific files to directory msdos
+- suppress the notion of partial flush to simplify the interface
+ (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4)
+- suppress history buffer provided by application to simplify the interface
+ (this feature was not implemented anyway in 1.0.4)
+- next_in and avail_in must be initialized before calling inflateInit or
+ inflateInit2
+- add EXPORT in all exported functions (for Windows DLL)
+- added Makefile.nt (thanks to Stephen Williams)
+- added the unsupported "contrib" directory:
+ contrib/asm386/ by Gilles Vollant <info@winimage.com>
+ 386 asm code replacing longest_match().
+ contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
+ A C++ I/O streams interface to the zlib gz* functions
+ contrib/iostream2/ by Tyge Løvset <Tyge.Lovset@cmr.no>
+ Another C++ I/O streams interface
+ contrib/untgz/ by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
+ A very simple tar.gz file extractor using zlib
+ contrib/visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
+ How to use compress(), uncompress() and the gz* functions from VB.
+- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression
+ level) in minigzip (thanks to Tom Lane)
+
+- use const for rommable constants in deflate
+- added test for gzseek and gztell in example.c
+- add undocumented function inflateSyncPoint() (hack for Paul Mackerras)
+- add undocumented function zError to convert error code to string
+ (for Tim Smithers)
+- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code.
+- Use default memcpy for Symantec MSDOS compiler.
+- Add EXPORT keyword for check_func (needed for Windows DLL)
+- add current directory to LD_LIBRARY_PATH for "make test"
+- create also a link for libz.so.1
+- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura)
+- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX)
+- added -soname for Linux in configure (Chun-Chung Chen,
+- assign numbers to the exported functions in zlib.def (for Windows DLL)
+- add advice in zlib.h for best usage of deflateSetDictionary
+- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn)
+- allow compilation with ANSI keywords only enabled for TurboC in large model
+- avoid "versionString"[0] (Borland bug)
+- add NEED_DUMMY_RETURN for Borland
+- use variable z_verbose for tracing in debug mode (L. Peter Deutsch).
+- allow compilation with CC
+- defined STDC for OS/2 (David Charlap)
+- limit external names to 8 chars for MVS (Thomas Lund)
+- in minigzip.c, use static buffers only for 16-bit systems
+- fix suffix check for "minigzip -d foo.gz"
+- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee)
+- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau)
+- added makelcc.bat for lcc-win32 (Tom St Denis)
+- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe)
+- Avoid expanded $Id: ChangeLog,v 1.1 2001/11/09 01:48:01 mpl Exp $. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion.
+- check for unistd.h in configure (for off_t)
+- remove useless check parameter in inflate_blocks_free
+- avoid useless assignment of s->check to itself in inflate_blocks_new
+- do not flush twice in gzclose (thanks to Ken Raeburn)
+- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h
+- use NO_ERRNO_H instead of enumeration of operating systems with errno.h
+- work around buggy fclose on pipes for HP/UX
+- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson)
+- fix configure if CC is already equal to gcc
+
+Changes in 1.0.5 (3 Jan 98)
+- Fix inflate to terminate gracefully when fed corrupted or invalid data
+- Use const for rommable constants in inflate
+- Eliminate memory leaks on error conditions in inflate
+- Removed some vestigial code in inflate
+- Update web address in README
+
+Changes in 1.0.4 (24 Jul 96)
+- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
+ bit, so the decompressor could decompress all the correct data but went
+ on to attempt decompressing extra garbage data. This affected minigzip too.
+- zlibVersion and gzerror return const char* (needed for DLL)
+- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
+- use z_error only for DEBUG (avoid problem with DLLs)
+
+Changes in 1.0.3 (2 Jul 96)
+- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS
+ small and medium models; this makes the library incompatible with previous
+ versions for these models. (No effect in large model or on other systems.)
+- return OK instead of BUF_ERROR if previous deflate call returned with
+ avail_out as zero but there is nothing to do
+- added memcmp for non STDC compilers
+- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly)
+- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO)
+- better check for 16-bit mode MSC (avoids problem with Symantec)
+
+Changes in 1.0.2 (23 May 96)
+- added Windows DLL support
+- added a function zlibVersion (for the DLL support)
+- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model)
+- Bytef is define's instead of typedef'd only for Borland C
+- avoid reading uninitialized memory in example.c
+- mention in README that the zlib format is now RFC1950
+- updated Makefile.dj2
+- added algorithm.doc
+
+Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion]
+- fix array overlay in deflate.c which sometimes caused bad compressed data
+- fix inflate bug with empty stored block
+- fix MSDOS medium model which was broken in 0.99
+- fix deflateParams() which could generated bad compressed data.
+- Bytef is define'd instead of typedef'ed (work around Borland bug)
+- added an INDEX file
+- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32),
+ Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas)
+- speed up adler32 for modern machines without auto-increment
+- added -ansi for IRIX in configure
+- static_init_done in trees.c is an int
+- define unlink as delete for VMS
+- fix configure for QNX
+- add configure branch for SCO and HPUX
+- avoid many warnings (unused variables, dead assignments, etc...)
+- no fdopen for BeOS
+- fix the Watcom fix for 32 bit mode (define FAR as empty)
+- removed redefinition of Byte for MKWERKS
+- work around an MWKERKS bug (incorrect merge of all .h files)
+
+Changes in 0.99 (27 Jan 96)
+- allow preset dictionary shared between compressor and decompressor
+- allow compression level 0 (no compression)
+- add deflateParams in zlib.h: allow dynamic change of compression level
+ and compression strategy.
+- test large buffers and deflateParams in example.c
+- add optional "configure" to build zlib as a shared library
+- suppress Makefile.qnx, use configure instead
+- fixed deflate for 64-bit systems (detected on Cray)
+- fixed inflate_blocks for 64-bit systems (detected on Alpha)
+- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2)
+- always return Z_BUF_ERROR when deflate() has nothing to do
+- deflateInit and inflateInit are now macros to allow version checking
+- prefix all global functions and types with z_ with -DZ_PREFIX
+- make falloc completely reentrant (inftrees.c)
+- fixed very unlikely race condition in ct_static_init
+- free in reverse order of allocation to help memory manager
+- use zlib-1.0/* instead of zlib/* inside the tar.gz
+- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith
+ -Wconversion -Wstrict-prototypes -Wmissing-prototypes"
+- allow gzread on concatenated .gz files
+- deflateEnd now returns Z_DATA_ERROR if it was premature
+- deflate is finally (?) fully deterministic (no matches beyond end of input)
+- Document Z_SYNC_FLUSH
+- add uninstall in Makefile
+- Check for __cpluplus in zlib.h
+- Better test in ct_align for partial flush
+- avoid harmless warnings for Borland C++
+- initialize hash_head in deflate.c
+- avoid warning on fdopen (gzio.c) for HP cc -Aa
+- include stdlib.h for STDC compilers
+- include errno.h for Cray
+- ignore error if ranlib doesn't exist
+- call ranlib twice for NeXTSTEP
+- use exec_prefix instead of prefix for libz.a
+- renamed ct_* as _tr_* to avoid conflict with applications
+- clear z->msg in inflateInit2 before any error return
+- initialize opaque in example.c, gzio.c, deflate.c and inflate.c
+- fixed typo in zconf.h (_GNUC__ => __GNUC__)
+- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode)
+- fix typo in Make_vms.com (f$trnlnm -> f$getsyi)
+- in fcalloc, normalize pointer if size > 65520 bytes
+- don't use special fcalloc for 32 bit Borland C++
+- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc...
+- use Z_BINARY instead of BINARY
+- document that gzclose after gzdopen will close the file
+- allow "a" as mode in gzopen.
+- fix error checking in gzread
+- allow skipping .gz extra-field on pipes
+- added reference to Perl interface in README
+- put the crc table in FAR data (I dislike more and more the medium model :)
+- added get_crc_table
+- added a dimension to all arrays (Borland C can't count).
+- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast
+- guard against multiple inclusion of *.h (for precompiled header on Mac)
+- Watcom C pretends to be Microsoft C small model even in 32 bit mode.
+- don't use unsized arrays to avoid silly warnings by Visual C++:
+ warning C4746: 'inflate_mask' : unsized array treated as '__far'
+ (what's wrong with far data in far model?).
+- define enum out of inflate_blocks_state to allow compilation with C++
+
+Changes in 0.95 (16 Aug 95)
+- fix MSDOS small and medium model (now easier to adapt to any compiler)
+- inlined send_bits
+- fix the final (:-) bug for deflate with flush (output was correct but
+ not completely flushed in rare occasions).
+- default window size is same for compression and decompression
+ (it's now sufficient to set MAX_WBITS in zconf.h).
+- voidp -> voidpf and voidnp -> voidp (for consistency with other
+ typedefs and because voidnp was not near in large model).
+
+Changes in 0.94 (13 Aug 95)
+- support MSDOS medium model
+- fix deflate with flush (could sometimes generate bad output)
+- fix deflateReset (zlib header was incorrectly suppressed)
+- added support for VMS
+- allow a compression level in gzopen()
+- gzflush now calls fflush
+- For deflate with flush, flush even if no more input is provided.
+- rename libgz.a as libz.a
+- avoid complex expression in infcodes.c triggering Turbo C bug
+- work around a problem with gcc on Alpha (in INSERT_STRING)
+- don't use inline functions (problem with some gcc versions)
+- allow renaming of Byte, uInt, etc... with #define.
+- avoid warning about (unused) pointer before start of array in deflate.c
+- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c
+- avoid reserved word 'new' in trees.c
+
+Changes in 0.93 (25 June 95)
+- temporarily disable inline functions
+- make deflate deterministic
+- give enough lookahead for PARTIAL_FLUSH
+- Set binary mode for stdin/stdout in minigzip.c for OS/2
+- don't even use signed char in inflate (not portable enough)
+- fix inflate memory leak for segmented architectures
+
+Changes in 0.92 (3 May 95)
+- don't assume that char is signed (problem on SGI)
+- Clear bit buffer when starting a stored block
+- no memcpy on Pyramid
+- suppressed inftest.c
+- optimized fill_window, put longest_match inline for gcc
+- optimized inflate on stored blocks.
+- untabify all sources to simplify patches
+
+Changes in 0.91 (2 May 95)
+- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h
+- Document the memory requirements in zconf.h
+- added "make install"
+- fix sync search logic in inflateSync
+- deflate(Z_FULL_FLUSH) now works even if output buffer too short
+- after inflateSync, don't scare people with just "lo world"
+- added support for DJGPP
+
+Changes in 0.9 (1 May 95)
+- don't assume that zalloc clears the allocated memory (the TurboC bug
+ was Mark's bug after all :)
+- let again gzread copy uncompressed data unchanged (was working in 0.71)
+- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented
+- added a test of inflateSync in example.c
+- moved MAX_WBITS to zconf.h because users might want to change that.
+- document explicitly that zalloc(64K) on MSDOS must return a normalized
+ pointer (zero offset)
+- added Makefiles for Microsoft C, Turbo C, Borland C++
+- faster crc32()
+
+Changes in 0.8 (29 April 95)
+- added fast inflate (inffast.c)
+- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this
+ is incompatible with previous versions of zlib which returned Z_OK.
+- work around a TurboC compiler bug (bad code for b << 0, see infutil.h)
+ (actually that was not a compiler bug, see 0.81 above)
+- gzread no longer reads one extra byte in certain cases
+- In gzio destroy(), don't reference a freed structure
+- avoid many warnings for MSDOS
+- avoid the ERROR symbol which is used by MS Windows
+
+Changes in 0.71 (14 April 95)
+- Fixed more MSDOS compilation problems :( There is still a bug with
+ TurboC large model.
+
+Changes in 0.7 (14 April 95)
+- Added full inflate support.
+- Simplified the crc32() interface. The pre- and post-conditioning
+ (one's complement) is now done inside crc32(). WARNING: this is
+ incompatible with previous versions; see zlib.h for the new usage.
+
+Changes in 0.61 (12 April 95)
+- workaround for a bug in TurboC. example and minigzip now work on MSDOS.
+
+Changes in 0.6 (11 April 95)
+- added minigzip.c
+- added gzdopen to reopen a file descriptor as gzFile
+- added transparent reading of non-gziped files in gzread.
+- fixed bug in gzread (don't read crc as data)
+- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose).
+- don't allocate big arrays in the stack (for MSDOS)
+- fix some MSDOS compilation problems
+
+Changes in 0.5:
+- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but
+ not yet Z_FULL_FLUSH.
+- support decompression but only in a single step (forced Z_FINISH)
+- added opaque object for zalloc and zfree.
+- added deflateReset and inflateReset
+- added a variable zlib_version for consistency checking.
+- renamed the 'filter' parameter of deflateInit2 as 'strategy'.
+ Added Z_FILTERED and Z_HUFFMAN_ONLY constants.
+
+Changes in 0.4:
+- avoid "zip" everywhere, use zlib instead of ziplib.
+- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
+ if compression method == 8.
+- added adler32 and crc32
+- renamed deflateOptions as deflateInit2, call one or the other but not both
+- added the method parameter for deflateInit2.
+- added inflateInit2
+- simplied considerably deflateInit and inflateInit by not supporting
+ user-provided history buffer. This is supported only in deflateInit2
+ and inflateInit2.
+
+Changes in 0.3:
+- prefix all macro names with Z_
+- use Z_FINISH instead of deflateEnd to finish compression.
+- added Z_HUFFMAN_ONLY
+- added gzerror()
diff --git a/cfe/cfe/zlib/FAQ b/cfe/cfe/zlib/FAQ
new file mode 100644
index 0000000..0feb6d3
--- /dev/null
+++ b/cfe/cfe/zlib/FAQ
@@ -0,0 +1,72 @@
+
+ Frequently Asked Questions about zlib
+
+
+If your question is not there, please check the zlib home page
+http://www.cdrom.com/pub/infozip/zlib/ which may have more recent information.
+
+
+1) I need a Windows DLL
+2) I need a Visual Basic interface to zlib
+3) compress() returns Z_BUF_ERROR
+4) deflate or inflate returns Z_BUF_ERROR
+5) Where is the zlib documentation (man pages, etc...)?
+6) Why don't you use GNU autoconf, libtool, etc...?
+7) There is a bug in zlib.
+8) I get "undefined reference to gzputc"
+
+
+
+1) I need a Windows DLL
+
+ The zlib sources can be compiled without change to produce a DLL.
+ If you want a precompiled DLL, see http://www.winimage.com/zLibDll
+
+
+2) I need a Visual Basic interface to zlib
+
+ See http://www.tcfb.com/dowseware/cmp-z-it.zip
+ http://web2.airmail.net/markn/articles/zlibtool/zlibtool.htm
+ and contrib/visual-basic.txt
+
+3) compress() returns Z_BUF_ERROR
+
+ Make sure that before the call of compress, the length of the
+ compressed buffer is equal to the total size of the compressed buffer
+ and not zero. For Visual Basic, check that this parameter is passed
+ by reference ("as any"), not by value ("as long").
+
+
+4) deflate or inflate returns Z_BUF_ERROR
+
+ Make sure that before the call avail_in and avail_out are not zero.
+
+
+5) Where is the zlib documentation (man pages, etc...)?
+
+ It's in zlib.h for the moment. Volunteers to transform this
+ to man pages, please contact jloup@gzip.org. Examples of zlib usage
+ are in the files example.c and minigzip.c.
+
+
+6) Why don't you use GNU autoconf, libtool, etc...?
+
+ Because we would like to keep zlib as a very small and simple package.
+ zlib is rather portable and doesn't need much configuration.
+
+
+7) There is a bug in zlib.
+
+ Most of the time, such problems are due to an incorrect usage
+ of zlib. Please try to reproduce the problem with a small
+ program and send us the corresponding source at zlib@quest.jpl.nasa.gov
+ Do not send multi-megabyte data files without prior agreement.
+
+
+8) I get "undefined reference to gzputc"
+
+ If "make test" produces something like
+ example.o(.text+0x174):
+ check that you don't have old files libz.* in /usr/lib, /usr/local/lib
+ or /usr/X11R6/lib. Remove old versions then do "make install".
+
diff --git a/cfe/cfe/zlib/INDEX b/cfe/cfe/zlib/INDEX
new file mode 100644
index 0000000..8a24576
--- /dev/null
+++ b/cfe/cfe/zlib/INDEX
@@ -0,0 +1,86 @@
+ChangeLog history of changes
+INDEX this file
+FAQ Frequently Asked Questions about zlib
+Make_vms.com script for Vax/VMS
+Makefile makefile for Unix (generated by configure)
+Makefile.in makefile for Unix (template for configure)
+Makefile.riscos makefile for RISCOS
+README guess what
+algorithm.txt description of the (de)compression algorithm
+configure configure script for Unix
+descrip.mms makefile for Vax/VMS
+zlib.3 mini man page for zlib (volunteers to write full
+ man pages from zlib.h welcome. write to jloup@gzip.org)
+
+amiga/Makefile.sas makefile for Amiga SAS/C
+amiga/Makefile.pup makefile for Amiga powerUP SAS/C PPC
+
+msdos/Makefile.w32 makefile for Microsoft Visual C++ 32-bit
+msdos/Makefile.b32 makefile for Borland C++ 32-bit
+msdos/Makefile.bor makefile for Borland C/C++ 16-bit
+msdos/Makefile.dj2 makefile for DJGPP 2.x
+msdos/Makefile.emx makefile for EMX 0.9c (32-bit DOS/OS2)
+msdos/Makefile.msc makefile for Microsoft C 16-bit
+msdos/Makefile.tc makefile for Turbo C
+msdos/Makefile.wat makefile for Watcom C
+msdos/zlib.def definition file for Windows DLL
+msdos/zlib.rc definition file for Windows DLL
+
+nt/Makefile.nt makefile for Windows NT
+nt/zlib.dnt definition file for Windows NT DLL
+nt/Makefile.emx makefile for EMX 0.9c/RSXNT 1.41 (Win32 Intel)
+nt/Makefile.gcc makefile for Windows NT using GCC (mingw32)
+
+
+ zlib public header files (must be kept):
+zconf.h
+zlib.h
+
+ private source files used to build the zlib library:
+adler32.c
+compress.c
+crc32.c
+deflate.c
+deflate.h
+gzio.c
+infblock.c
+infblock.h
+infcodes.c
+infcodes.h
+inffast.c
+inffast.h
+inflate.c
+inftrees.c
+inftrees.h
+infutil.c
+infutil.h
+maketree.c
+trees.c
+uncompr.c
+zutil.c
+zutil.h
+
+ source files for sample programs:
+example.c
+minigzip.c
+
+ unsupported contribution by third parties
+
+contrib/asm386/ by Gilles Vollant <info@winimage.com>
+ 386 asm code replacing longest_match().
+
+contrib/minizip/ by Gilles Vollant <info@winimage.com>
+ Mini zip and unzip based on zlib
+ See http://www.winimage.com/zLibDll/unzip.html
+
+contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
+ A C++ I/O streams interface to the zlib gz* functions
+
+contrib/iostream2/ by Tyge Løvset <Tyge.Lovset@cmr.no>
+ Another C++ I/O streams interface
+
+contrib/untgz/ by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
+ A very simple tar.gz extractor using zlib
+
+contrib/visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
+ How to use compress(), uncompress() and the gz* functions from VB.
diff --git a/cfe/cfe/zlib/Make_vms.com b/cfe/cfe/zlib/Make_vms.com
new file mode 100644
index 0000000..1c57e8f
--- /dev/null
+++ b/cfe/cfe/zlib/Make_vms.com
@@ -0,0 +1,115 @@
+$! make libz under VMS
+$! written by Martin P.J. Zinser <m.zinser@gsi.de>
+$!
+$! Look for the compiler used
+$!
+$ ccopt = ""
+$ if f$getsyi("HW_MODEL").ge.1024
+$ then
+$ ccopt = "/prefix=all"+ccopt
+$ comp = "__decc__=1"
+$ if f$trnlnm("SYS").eqs."" then define sys sys$library:
+$ else
+$ if f$search("SYS$SYSTEM:DECC$COMPILER.EXE").eqs.""
+$ then
+$ comp = "__vaxc__=1"
+$ if f$trnlnm("SYS").eqs."" then define sys sys$library:
+$ else
+$ if f$trnlnm("SYS").eqs."" then define sys decc$library_include:
+$ ccopt = "/decc/prefix=all"+ccopt
+$ comp = "__decc__=1"
+$ endif
+$ endif
+$!
+$! Build the thing plain or with mms
+$!
+$ write sys$output "Compiling Zlib sources ..."
+$ if f$search("SYS$SYSTEM:MMS.EXE").eqs.""
+$ then
+$ dele example.obj;*,minigzip.obj;*
+$ CALL MAKE adler32.OBJ "CC ''CCOPT' adler32" -
+ adler32.c zlib.h zconf.h
+$ CALL MAKE compress.OBJ "CC ''CCOPT' compress" -
+ compress.c zlib.h zconf.h
+$ CALL MAKE crc32.OBJ "CC ''CCOPT' crc32" -
+ crc32.c zlib.h zconf.h
+$ CALL MAKE deflate.OBJ "CC ''CCOPT' deflate" -
+ deflate.c deflate.h zutil.h zlib.h zconf.h
+$ CALL MAKE gzio.OBJ "CC ''CCOPT' gzio" -
+ gzio.c zutil.h zlib.h zconf.h
+$ CALL MAKE infblock.OBJ "CC ''CCOPT' infblock" -
+ infblock.c zutil.h zlib.h zconf.h infblock.h
+$ CALL MAKE infcodes.OBJ "CC ''CCOPT' infcodes" -
+ infcodes.c zutil.h zlib.h zconf.h inftrees.h
+$ CALL MAKE inffast.OBJ "CC ''CCOPT' inffast" -
+ inffast.c zutil.h zlib.h zconf.h inffast.h
+$ CALL MAKE inflate.OBJ "CC ''CCOPT' inflate" -
+ inflate.c zutil.h zlib.h zconf.h infblock.h
+$ CALL MAKE inftrees.OBJ "CC ''CCOPT' inftrees" -
+ inftrees.c zutil.h zlib.h zconf.h inftrees.h
+$ CALL MAKE infutil.OBJ "CC ''CCOPT' infutil" -
+ infutil.c zutil.h zlib.h zconf.h inftrees.h infutil.h
+$ CALL MAKE trees.OBJ "CC ''CCOPT' trees" -
+ trees.c deflate.h zutil.h zlib.h zconf.h
+$ CALL MAKE uncompr.OBJ "CC ''CCOPT' uncompr" -
+ uncompr.c zlib.h zconf.h
+$ CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" -
+ zutil.c zutil.h zlib.h zconf.h
+$ write sys$output "Building Zlib ..."
+$ CALL MAKE libz.OLB "lib/crea libz.olb *.obj" *.OBJ
+$ write sys$output "Building example..."
+$ CALL MAKE example.OBJ "CC ''CCOPT' example" -
+ example.c zlib.h zconf.h
+$ call make example.exe "LINK example,libz.olb/lib" example.obj libz.olb
+$ write sys$output "Building minigzip..."
+$ CALL MAKE minigzip.OBJ "CC ''CCOPT' minigzip" -
+ minigzip.c zlib.h zconf.h
+$ call make minigzip.exe -
+ "LINK minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib" -
+ minigzip.obj libz.olb
+$ else
+$ mms/macro=('comp')
+$ endif
+$ write sys$output "Zlib build completed"
+$ exit
+$!
+$!
+$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES
+$ V = 'F$Verify(0)
+$! P1 = What we are trying to make
+$! P2 = Command to make it
+$! P3 - P8 What it depends on
+$
+$ If F$Search(P1) .Eqs. "" Then Goto Makeit
+$ Time = F$CvTime(F$File(P1,"RDT"))
+$arg=3
+$Loop:
+$ Argument = P'arg
+$ If Argument .Eqs. "" Then Goto Exit
+$ El=0
+$Loop2:
+$ File = F$Element(El," ",Argument)
+$ If File .Eqs. " " Then Goto Endl
+$ AFile = ""
+$Loop3:
+$ OFile = AFile
+$ AFile = F$Search(File)
+$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl
+$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit
+$ Goto Loop3
+$NextEL:
+$ El = El + 1
+$ Goto Loop2
+$EndL:
+$ arg=arg+1
+$ If arg .Le. 8 Then Goto Loop
+$ Goto Exit
+$
+$Makeit:
+$ VV=F$VERIFY(0)
+$ write sys$output P2
+$ 'P2
+$ VV='F$Verify(VV)
+$Exit:
+$ If V Then Set Verify
+$ENDSUBROUTINE
diff --git a/cfe/cfe/zlib/Makefile b/cfe/cfe/zlib/Makefile
new file mode 100644
index 0000000..e9224bb
--- /dev/null
+++ b/cfe/cfe/zlib/Makefile
@@ -0,0 +1,28 @@
+
+#ALLOBJS += adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
+# zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o
+
+#ALLOBJS += adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
+# zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o
+
+ALLOBJS += adler32.o uncompr.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o zutil.o
+CFLAGS += -DCFG_ZLIB=1 -DMY_ZCALLOC -DNO_MEMCPY
+
+adler32.o: zlib.h zconf.h
+compress.o: zlib.h zconf.h
+crc32.o: zlib.h zconf.h
+deflate.o: deflate.h zutil.h zlib.h zconf.h
+example.o: zlib.h zconf.h
+gzio.o: zutil.h zlib.h zconf.h
+infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h
+infcodes.o: zutil.h zlib.h zconf.h
+infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h
+inffast.o: zutil.h zlib.h zconf.h inftrees.h
+inffast.o: infblock.h infcodes.h infutil.h inffast.h
+inflate.o: zutil.h zlib.h zconf.h infblock.h
+inftrees.o: zutil.h zlib.h zconf.h inftrees.h
+infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h
+minigzip.o: zlib.h zconf.h
+trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
+uncompr.o: zlib.h zconf.h
+zutil.o: zutil.h zlib.h zconf.h
diff --git a/cfe/cfe/zlib/Makefile.in b/cfe/cfe/zlib/Makefile.in
new file mode 100644
index 0000000..3a3b116
--- /dev/null
+++ b/cfe/cfe/zlib/Makefile.in
@@ -0,0 +1,174 @@
+# Makefile for zlib
+# Copyright (C) 1995-1998 Jean-loup Gailly.
+# For conditions of distribution and use, see copyright notice in zlib.h
+
+# To compile and test, type:
+# ./configure; make test
+# The call of configure is optional if you don't have special requirements
+# If you wish to build zlib as a shared library, use: ./configure -s
+
+# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
+# make install
+# To install in $HOME instead of /usr/local, use:
+# make install prefix=$HOME
+
+CC=cc
+
+CFLAGS=-O
+#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
+#CFLAGS=-g -DDEBUG
+#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+# -Wstrict-prototypes -Wmissing-prototypes
+
+LDFLAGS=-L. -lz
+LDSHARED=$(CC)
+CPP=$(CC) -E
+
+VER=1.1.3
+LIBS=libz.a
+SHAREDLIB=libz.so
+
+AR=ar rc
+RANLIB=ranlib
+TAR=tar
+SHELL=/bin/sh
+
+prefix = /usr/local
+exec_prefix = ${prefix}
+libdir = ${exec_prefix}/lib
+includedir = ${prefix}/include
+
+OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
+ zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o
+
+OBJA =
+# to use the asm code: make OBJA=match.o
+
+TEST_OBJS = example.o minigzip.o
+
+DISTFILES = README FAQ INDEX ChangeLog configure Make*[a-z0-9] *.[ch] *.mms \
+ algorithm.txt zlib.3 msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \
+ nt/Make*[a-z0-9] nt/zlib.dnt amiga/Make*.??? os2/M*.os2 os2/zlib.def \
+ contrib/RE*.contrib contrib/*.txt contrib/asm386/*.asm contrib/asm386/*.c \
+ contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/asm[56]86/*.?86 \
+ contrib/asm[56]86/*.S contrib/iostream/*.cpp \
+ contrib/iostream/*.h contrib/iostream2/*.h contrib/iostream2/*.cpp \
+ contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32 \
+ contrib/minizip/[CM]*[pe] contrib/minizip/*.[ch] contrib/minizip/*.[td]?? \
+ contrib/delphi*/*.???
+
+all: example minigzip
+
+test: all
+ @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
+ echo hello world | ./minigzip | ./minigzip -d || \
+ echo ' *** minigzip test FAILED ***' ; \
+ if ./example; then \
+ echo ' *** zlib test OK ***'; \
+ else \
+ echo ' *** zlib test FAILED ***'; \
+ fi
+
+libz.a: $(OBJS) $(OBJA)
+ $(AR) $@ $(OBJS) $(OBJA)
+ -@ ($(RANLIB) $@ || true) >/dev/null 2>&1
+
+match.o: match.S
+ $(CPP) match.S > _match.s
+ $(CC) -c _match.s
+ mv _match.o match.o
+ rm -f _match.s
+
+$(SHAREDLIB).$(VER): $(OBJS)
+ $(LDSHARED) -o $@ $(OBJS)
+ rm -f $(SHAREDLIB) $(SHAREDLIB).1
+ ln -s $@ $(SHAREDLIB)
+ ln -s $@ $(SHAREDLIB).1
+
+example: example.o $(LIBS)
+ $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)
+
+minigzip: minigzip.o $(LIBS)
+ $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
+
+install: $(LIBS)
+ -@if [ ! -d $(includedir) ]; then mkdir $(includedir); fi
+ -@if [ ! -d $(libdir) ]; then mkdir $(libdir); fi
+ cp zlib.h zconf.h $(includedir)
+ chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h
+ cp $(LIBS) $(libdir)
+ cd $(libdir); chmod 755 $(LIBS)
+ -@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1
+ cd $(libdir); if test -f $(SHAREDLIB).$(VER); then \
+ rm -f $(SHAREDLIB) $(SHAREDLIB).1; \
+ ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB); \
+ ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB).1; \
+ (ldconfig || true) >/dev/null 2>&1; \
+ fi
+# The ranlib in install is needed on NeXTSTEP which checks file times
+# ldconfig is for Linux
+
+uninstall:
+ cd $(includedir); \
+ v=$(VER); \
+ if test -f zlib.h; then \
+ v=`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`; \
+ rm -f zlib.h zconf.h; \
+ fi; \
+ cd $(libdir); rm -f libz.a; \
+ if test -f $(SHAREDLIB).$$v; then \
+ rm -f $(SHAREDLIB).$$v $(SHAREDLIB) $(SHAREDLIB).1; \
+ fi
+
+clean:
+ rm -f *.o *~ example minigzip libz.a libz.so* foo.gz so_locations \
+ _match.s maketree
+
+distclean: clean
+
+zip:
+ mv Makefile Makefile~; cp -p Makefile.in Makefile
+ rm -f test.c ztest*.c contrib/minizip/test.zip
+ v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\
+ zip -ul9 zlib$$v $(DISTFILES)
+ mv Makefile~ Makefile
+
+dist:
+ mv Makefile Makefile~; cp -p Makefile.in Makefile
+ rm -f test.c ztest*.c contrib/minizip/test.zip
+ d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\
+ rm -f $$d.tar.gz; \
+ if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \
+ files=""; \
+ for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \
+ cd ..; \
+ GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \
+ if test ! -d $$d; then rm -f $$d; fi
+ mv Makefile~ Makefile
+
+tags:
+ etags *.[ch]
+
+depend:
+ makedepend -- $(CFLAGS) -- *.[ch]
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+adler32.o: zlib.h zconf.h
+compress.o: zlib.h zconf.h
+crc32.o: zlib.h zconf.h
+deflate.o: deflate.h zutil.h zlib.h zconf.h
+example.o: zlib.h zconf.h
+gzio.o: zutil.h zlib.h zconf.h
+infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h
+infcodes.o: zutil.h zlib.h zconf.h
+infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h
+inffast.o: zutil.h zlib.h zconf.h inftrees.h
+inffast.o: infblock.h infcodes.h infutil.h inffast.h
+inflate.o: zutil.h zlib.h zconf.h infblock.h
+inftrees.o: zutil.h zlib.h zconf.h inftrees.h
+infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h
+minigzip.o: zlib.h zconf.h
+trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
+uncompr.o: zlib.h zconf.h
+zutil.o: zutil.h zlib.h zconf.h
diff --git a/cfe/cfe/zlib/Makefile.orig b/cfe/cfe/zlib/Makefile.orig
new file mode 100644
index 0000000..3a3b116
--- /dev/null
+++ b/cfe/cfe/zlib/Makefile.orig
@@ -0,0 +1,174 @@
+# Makefile for zlib
+# Copyright (C) 1995-1998 Jean-loup Gailly.
+# For conditions of distribution and use, see copyright notice in zlib.h
+
+# To compile and test, type:
+# ./configure; make test
+# The call of configure is optional if you don't have special requirements
+# If you wish to build zlib as a shared library, use: ./configure -s
+
+# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
+# make install
+# To install in $HOME instead of /usr/local, use:
+# make install prefix=$HOME
+
+CC=cc
+
+CFLAGS=-O
+#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
+#CFLAGS=-g -DDEBUG
+#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+# -Wstrict-prototypes -Wmissing-prototypes
+
+LDFLAGS=-L. -lz
+LDSHARED=$(CC)
+CPP=$(CC) -E
+
+VER=1.1.3
+LIBS=libz.a
+SHAREDLIB=libz.so
+
+AR=ar rc
+RANLIB=ranlib
+TAR=tar
+SHELL=/bin/sh
+
+prefix = /usr/local
+exec_prefix = ${prefix}
+libdir = ${exec_prefix}/lib
+includedir = ${prefix}/include
+
+OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
+ zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o
+
+OBJA =
+# to use the asm code: make OBJA=match.o
+
+TEST_OBJS = example.o minigzip.o
+
+DISTFILES = README FAQ INDEX ChangeLog configure Make*[a-z0-9] *.[ch] *.mms \
+ algorithm.txt zlib.3 msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \
+ nt/Make*[a-z0-9] nt/zlib.dnt amiga/Make*.??? os2/M*.os2 os2/zlib.def \
+ contrib/RE*.contrib contrib/*.txt contrib/asm386/*.asm contrib/asm386/*.c \
+ contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/asm[56]86/*.?86 \
+ contrib/asm[56]86/*.S contrib/iostream/*.cpp \
+ contrib/iostream/*.h contrib/iostream2/*.h contrib/iostream2/*.cpp \
+ contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32 \
+ contrib/minizip/[CM]*[pe] contrib/minizip/*.[ch] contrib/minizip/*.[td]?? \
+ contrib/delphi*/*.???
+
+all: example minigzip
+
+test: all
+ @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
+ echo hello world | ./minigzip | ./minigzip -d || \
+ echo ' *** minigzip test FAILED ***' ; \
+ if ./example; then \
+ echo ' *** zlib test OK ***'; \
+ else \
+ echo ' *** zlib test FAILED ***'; \
+ fi
+
+libz.a: $(OBJS) $(OBJA)
+ $(AR) $@ $(OBJS) $(OBJA)
+ -@ ($(RANLIB) $@ || true) >/dev/null 2>&1
+
+match.o: match.S
+ $(CPP) match.S > _match.s
+ $(CC) -c _match.s
+ mv _match.o match.o
+ rm -f _match.s
+
+$(SHAREDLIB).$(VER): $(OBJS)
+ $(LDSHARED) -o $@ $(OBJS)
+ rm -f $(SHAREDLIB) $(SHAREDLIB).1
+ ln -s $@ $(SHAREDLIB)
+ ln -s $@ $(SHAREDLIB).1
+
+example: example.o $(LIBS)
+ $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)
+
+minigzip: minigzip.o $(LIBS)
+ $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
+
+install: $(LIBS)
+ -@if [ ! -d $(includedir) ]; then mkdir $(includedir); fi
+ -@if [ ! -d $(libdir) ]; then mkdir $(libdir); fi
+ cp zlib.h zconf.h $(includedir)
+ chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h
+ cp $(LIBS) $(libdir)
+ cd $(libdir); chmod 755 $(LIBS)
+ -@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1
+ cd $(libdir); if test -f $(SHAREDLIB).$(VER); then \
+ rm -f $(SHAREDLIB) $(SHAREDLIB).1; \
+ ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB); \
+ ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB).1; \
+ (ldconfig || true) >/dev/null 2>&1; \
+ fi
+# The ranlib in install is needed on NeXTSTEP which checks file times
+# ldconfig is for Linux
+
+uninstall:
+ cd $(includedir); \
+ v=$(VER); \
+ if test -f zlib.h; then \
+ v=`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`; \
+ rm -f zlib.h zconf.h; \
+ fi; \
+ cd $(libdir); rm -f libz.a; \
+ if test -f $(SHAREDLIB).$$v; then \
+ rm -f $(SHAREDLIB).$$v $(SHAREDLIB) $(SHAREDLIB).1; \
+ fi
+
+clean:
+ rm -f *.o *~ example minigzip libz.a libz.so* foo.gz so_locations \
+ _match.s maketree
+
+distclean: clean
+
+zip:
+ mv Makefile Makefile~; cp -p Makefile.in Makefile
+ rm -f test.c ztest*.c contrib/minizip/test.zip
+ v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\
+ zip -ul9 zlib$$v $(DISTFILES)
+ mv Makefile~ Makefile
+
+dist:
+ mv Makefile Makefile~; cp -p Makefile.in Makefile
+ rm -f test.c ztest*.c contrib/minizip/test.zip
+ d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\
+ rm -f $$d.tar.gz; \
+ if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \
+ files=""; \
+ for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \
+ cd ..; \
+ GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \
+ if test ! -d $$d; then rm -f $$d; fi
+ mv Makefile~ Makefile
+
+tags:
+ etags *.[ch]
+
+depend:
+ makedepend -- $(CFLAGS) -- *.[ch]
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+adler32.o: zlib.h zconf.h
+compress.o: zlib.h zconf.h
+crc32.o: zlib.h zconf.h
+deflate.o: deflate.h zutil.h zlib.h zconf.h
+example.o: zlib.h zconf.h
+gzio.o: zutil.h zlib.h zconf.h
+infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h
+infcodes.o: zutil.h zlib.h zconf.h
+infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h
+inffast.o: zutil.h zlib.h zconf.h inftrees.h
+inffast.o: infblock.h infcodes.h infutil.h inffast.h
+inflate.o: zutil.h zlib.h zconf.h infblock.h
+inftrees.o: zutil.h zlib.h zconf.h inftrees.h
+infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h
+minigzip.o: zlib.h zconf.h
+trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
+uncompr.o: zlib.h zconf.h
+zutil.o: zutil.h zlib.h zconf.h
diff --git a/cfe/cfe/zlib/Makefile.riscos b/cfe/cfe/zlib/Makefile.riscos
new file mode 100644
index 0000000..d97f449
--- /dev/null
+++ b/cfe/cfe/zlib/Makefile.riscos
@@ -0,0 +1,151 @@
+# Project: zlib_1_03
+# Patched for zlib 1.1.2 rw@shadow.org.uk 19980430
+# test works out-of-the-box, installs `somewhere' on demand
+
+# Toolflags:
+CCflags = -c -depend !Depend -IC: -g -throwback -DRISCOS -fah
+C++flags = -c -depend !Depend -IC: -throwback
+Linkflags = -aif -c++ -o $@
+ObjAsmflags = -throwback -NoCache -depend !Depend
+CMHGflags =
+LibFileflags = -c -l -o $@
+Squeezeflags = -o $@
+
+# change the line below to where _you_ want the library installed.
+libdest = lib:zlib
+
+# Final targets:
+@.lib: @.o.adler32 @.o.compress @.o.crc32 @.o.deflate @.o.gzio \
+ @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil @.o.trees \
+ @.o.uncompr @.o.zutil
+ LibFile $(LibFileflags) @.o.adler32 @.o.compress @.o.crc32 @.o.deflate \
+ @.o.gzio @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil \
+ @.o.trees @.o.uncompr @.o.zutil
+test: @.minigzip @.example @.lib
+ @copy @.lib @.libc A~C~DF~L~N~P~Q~RS~TV
+ @echo running tests: hang on.
+ @/@.minigzip -f -9 libc
+ @/@.minigzip -d libc-gz
+ @/@.minigzip -f -1 libc
+ @/@.minigzip -d libc-gz
+ @/@.minigzip -h -9 libc
+ @/@.minigzip -d libc-gz
+ @/@.minigzip -h -1 libc
+ @/@.minigzip -d libc-gz
+ @/@.minigzip -9 libc
+ @/@.minigzip -d libc-gz
+ @/@.minigzip -1 libc
+ @/@.minigzip -d libc-gz
+ @diff @.lib @.libc
+ @echo that should have reported '@.lib and @.libc identical' if you have diff.
+ @/@.example @.fred @.fred
+ @echo that will have given lots of hello!'s.
+
+@.minigzip: @.o.minigzip @.lib C:o.Stubs
+ Link $(Linkflags) @.o.minigzip @.lib C:o.Stubs
+@.example: @.o.example @.lib C:o.Stubs
+ Link $(Linkflags) @.o.example @.lib C:o.Stubs
+
+install: @.lib
+ cdir $(libdest)
+ cdir $(libdest).h
+ @copy @.h.zlib $(libdest).h.zlib A~C~DF~L~N~P~Q~RS~TV
+ @copy @.h.zconf $(libdest).h.zconf A~C~DF~L~N~P~Q~RS~TV
+ @copy @.lib $(libdest).lib A~C~DF~L~N~P~Q~RS~TV
+ @echo okay, installed zlib in $(libdest)
+
+clean:; remove @.minigzip
+ remove @.example
+ remove @.libc
+ -wipe @.o.* F~r~cV
+ remove @.fred
+
+# User-editable dependencies:
+.c.o:
+ cc $(ccflags) -o $@ $<
+
+# Static dependencies:
+
+# Dynamic dependencies:
+o.example: c.example
+o.example: h.zlib
+o.example: h.zconf
+o.minigzip: c.minigzip
+o.minigzip: h.zlib
+o.minigzip: h.zconf
+o.adler32: c.adler32
+o.adler32: h.zlib
+o.adler32: h.zconf
+o.compress: c.compress
+o.compress: h.zlib
+o.compress: h.zconf
+o.crc32: c.crc32
+o.crc32: h.zlib
+o.crc32: h.zconf
+o.deflate: c.deflate
+o.deflate: h.deflate
+o.deflate: h.zutil
+o.deflate: h.zlib
+o.deflate: h.zconf
+o.gzio: c.gzio
+o.gzio: h.zutil
+o.gzio: h.zlib
+o.gzio: h.zconf
+o.infblock: c.infblock
+o.infblock: h.zutil
+o.infblock: h.zlib
+o.infblock: h.zconf
+o.infblock: h.infblock
+o.infblock: h.inftrees
+o.infblock: h.infcodes
+o.infblock: h.infutil
+o.infcodes: c.infcodes
+o.infcodes: h.zutil
+o.infcodes: h.zlib
+o.infcodes: h.zconf
+o.infcodes: h.inftrees
+o.infcodes: h.infblock
+o.infcodes: h.infcodes
+o.infcodes: h.infutil
+o.infcodes: h.inffast
+o.inffast: c.inffast
+o.inffast: h.zutil
+o.inffast: h.zlib
+o.inffast: h.zconf
+o.inffast: h.inftrees
+o.inffast: h.infblock
+o.inffast: h.infcodes
+o.inffast: h.infutil
+o.inffast: h.inffast
+o.inflate: c.inflate
+o.inflate: h.zutil
+o.inflate: h.zlib
+o.inflate: h.zconf
+o.inflate: h.infblock
+o.inftrees: c.inftrees
+o.inftrees: h.zutil
+o.inftrees: h.zlib
+o.inftrees: h.zconf
+o.inftrees: h.inftrees
+o.inftrees: h.inffixed
+o.infutil: c.infutil
+o.infutil: h.zutil
+o.infutil: h.zlib
+o.infutil: h.zconf
+o.infutil: h.infblock
+o.infutil: h.inftrees
+o.infutil: h.infcodes
+o.infutil: h.infutil
+o.trees: c.trees
+o.trees: h.deflate
+o.trees: h.zutil
+o.trees: h.zlib
+o.trees: h.zconf
+o.trees: h.trees
+o.uncompr: c.uncompr
+o.uncompr: h.zlib
+o.uncompr: h.zconf
+o.zutil: c.zutil
+o.zutil: h.zutil
+o.zutil: h.zlib
+o.zutil: h.zconf
diff --git a/cfe/cfe/zlib/README b/cfe/cfe/zlib/README
new file mode 100644
index 0000000..8ff4587
--- /dev/null
+++ b/cfe/cfe/zlib/README
@@ -0,0 +1,148 @@
+zlib 1.1.3 is a general purpose data compression library. All the code
+is thread safe. The data format used by the zlib library
+is described by RFCs (Request for Comments) 1950 to 1952 in the files
+ftp://ds.internic.net/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate
+format) and rfc1952.txt (gzip format). These documents are also available in
+other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
+
+All functions of the compression library are documented in the file zlib.h
+(volunteer to write man pages welcome, contact jloup@gzip.org). A usage
+example of the library is given in the file example.c which also tests that
+the library is working correctly. Another example is given in the file
+minigzip.c. The compression library itself is composed of all source files
+except example.c and minigzip.c.
+
+To compile all files and run the test program, follow the instructions
+given at the top of Makefile. In short "make test; make install"
+should work for most machines. For Unix: "configure; make test; make install"
+For MSDOS, use one of the special makefiles such as Makefile.msc.
+For VMS, use Make_vms.com or descrip.mms.
+
+Questions about zlib should be sent to <zlib@quest.jpl.nasa.gov>, or to
+Gilles Vollant <info@winimage.com> for the Windows DLL version.
+The zlib home page is http://www.cdrom.com/pub/infozip/zlib/
+The official zlib ftp site is ftp://ftp.cdrom.com/pub/infozip/zlib/
+Before reporting a problem, please check those sites to verify that
+you have the latest version of zlib; otherwise get the latest version and
+check whether the problem still exists or not.
+
+Mark Nelson <markn@tiny.com> wrote an article about zlib for the Jan. 1997
+issue of Dr. Dobb's Journal; a copy of the article is available in
+http://web2.airmail.net/markn/articles/zlibtool/zlibtool.htm
+
+The changes made in version 1.1.3 are documented in the file ChangeLog.
+The main changes since 1.1.2 are:
+
+- fix "an inflate input buffer bug that shows up on rare but persistent
+ occasions" (Mark)
+- fix gzread and gztell for concatenated .gz files (Didier Le Botlan)
+- fix gzseek(..., SEEK_SET) in write mode
+- fix crc check after a gzeek (Frank Faubert)
+- fix miniunzip when the last entry in a zip file is itself a zip file
+ (J Lillge)
+- add contrib/asm586 and contrib/asm686 (Brian Raiter)
+ See http://www.muppetlabs.com/~breadbox/software/assembly.html
+- add support for Delphi 3 in contrib/delphi (Bob Dellaca)
+- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti)
+- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren)
+- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks)
+- added a FAQ file
+
+plus many changes for portability.
+
+Unsupported third party contributions are provided in directory "contrib".
+
+A Java implementation of zlib is available in the Java Development Kit 1.1
+http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html
+See the zlib home page http://www.cdrom.com/pub/infozip/zlib/ for details.
+
+A Perl interface to zlib written by Paul Marquess <pmarquess@bfsec.bt.co.uk>
+is in the CPAN (Comprehensive Perl Archive Network) sites, such as:
+ftp://ftp.cis.ufl.edu/pub/perl/CPAN/modules/by-module/Compress/Compress-Zlib*
+
+A Python interface to zlib written by A.M. Kuchling <amk@magnet.com>
+is available in Python 1.5 and later versions, see
+http://www.python.org/doc/lib/module-zlib.html
+
+A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com>
+is availlable at http://www.westend.com/~kupries/doc/trf/man/man.html
+
+An experimental package to read and write files in .zip format,
+written on top of zlib by Gilles Vollant <info@winimage.com>, is
+available at http://www.winimage.com/zLibDll/unzip.html
+and also in the contrib/minizip directory of zlib.
+
+
+Notes for some targets:
+
+- To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc
+ and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL
+ The zlib DLL support was initially done by Alessandro Iacopetti and is
+ now maintained by Gilles Vollant <info@winimage.com>. Check the zlib DLL
+ home page at http://www.winimage.com/zLibDll
+
+ From Visual Basic, you can call the DLL functions which do not take
+ a structure as argument: compress, uncompress and all gz* functions.
+ See contrib/visual-basic.txt for more information, or get
+ http://www.tcfb.com/dowseware/cmp-z-it.zip
+
+- For 64-bit Irix, deflate.c must be compiled without any optimization.
+ With -O, one libpng test fails. The test works in 32 bit mode (with
+ the -n32 compiler flag). The compiler bug has been reported to SGI.
+
+- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1
+ it works when compiled with cc.
+
+- on Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1
+ is necessary to get gzprintf working correctly. This is done by configure.
+
+- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works
+ with other compilers. Use "make test" to check your compiler.
+
+- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers.
+
+- For Turbo C the small model is supported only with reduced performance to
+ avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
+
+- For PalmOs, see http://www.cs.uit.no/~perm/PASTA/pilot/software.html
+ Per Harald Myrvang <perm@stud.cs.uit.no>
+
+
+Acknowledgments:
+
+ The deflate format used by zlib was defined by Phil Katz. The deflate
+ and zlib specifications were written by L. Peter Deutsch. Thanks to all the
+ people who reported problems and suggested various improvements in zlib;
+ they are too numerous to cite here.
+
+Copyright notice:
+
+ (C) 1995-1998 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not*
+receiving lengthy legal documents to sign. The sources are provided
+for free but without warranty of any kind. The library has been
+entirely written by Jean-loup Gailly and Mark Adler; it does not
+include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include
+in the file ChangeLog history information documenting your changes.
diff --git a/cfe/cfe/zlib/adler32.c b/cfe/cfe/zlib/adler32.c
new file mode 100644
index 0000000..70d368e
--- /dev/null
+++ b/cfe/cfe/zlib/adler32.c
@@ -0,0 +1,48 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: adler32.c,v 1.1 2001/11/09 01:48:01 mpl Exp $ */
+
+#include "zlib.h"
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+ uLong adler;
+ const Bytef *buf;
+ uInt len;
+{
+ unsigned long s1 = adler & 0xffff;
+ unsigned long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ if (buf == Z_NULL) return 1L;
+
+ while (len > 0) {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16) {
+ DO16(buf);
+ buf += 16;
+ k -= 16;
+ }
+ if (k != 0) do {
+ s1 += *buf++;
+ s2 += s1;
+ } while (--k);
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+}
diff --git a/cfe/cfe/zlib/algorithm.txt b/cfe/cfe/zlib/algorithm.txt
new file mode 100644
index 0000000..cdc830b
--- /dev/null
+++ b/cfe/cfe/zlib/algorithm.txt
@@ -0,0 +1,213 @@
+1. Compression algorithm (deflate)
+
+The deflation algorithm used by gzip (also zip and zlib) is a variation of
+LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
+the input data. The second occurrence of a string is replaced by a
+pointer to the previous string, in the form of a pair (distance,
+length). Distances are limited to 32K bytes, and lengths are limited
+to 258 bytes. When a string does not occur anywhere in the previous
+32K bytes, it is emitted as a sequence of literal bytes. (In this
+description, `string' must be taken as an arbitrary sequence of bytes,
+and is not restricted to printable characters.)
+
+Literals or match lengths are compressed with one Huffman tree, and
+match distances are compressed with another tree. The trees are stored
+in a compact form at the start of each block. The blocks can have any
+size (except that the compressed data for one block must fit in
+available memory). A block is terminated when deflate() determines that
+it would be useful to start another block with fresh trees. (This is
+somewhat similar to the behavior of LZW-based _compress_.)
+
+Duplicated strings are found using a hash table. All input strings of
+length 3 are inserted in the hash table. A hash index is computed for
+the next 3 bytes. If the hash chain for this index is not empty, all
+strings in the chain are compared with the current input string, and
+the longest match is selected.
+
+The hash chains are searched starting with the most recent strings, to
+favor small distances and thus take advantage of the Huffman encoding.
+The hash chains are singly linked. There are no deletions from the
+hash chains, the algorithm simply discards matches that are too old.
+
+To avoid a worst-case situation, very long hash chains are arbitrarily
+truncated at a certain length, determined by a runtime option (level
+parameter of deflateInit). So deflate() does not always find the longest
+possible match but generally finds a match which is long enough.
+
+deflate() also defers the selection of matches with a lazy evaluation
+mechanism. After a match of length N has been found, deflate() searches for
+a longer match at the next input byte. If a longer match is found, the
+previous match is truncated to a length of one (thus producing a single
+literal byte) and the process of lazy evaluation begins again. Otherwise,
+the original match is kept, and the next match search is attempted only N
+steps later.
+
+The lazy match evaluation is also subject to a runtime parameter. If
+the current match is long enough, deflate() reduces the search for a longer
+match, thus speeding up the whole process. If compression ratio is more
+important than speed, deflate() attempts a complete second search even if
+the first match is already long enough.
+
+The lazy match evaluation is not performed for the fastest compression
+modes (level parameter 1 to 3). For these fast modes, new strings
+are inserted in the hash table only when no match was found, or
+when the match is not too long. This degrades the compression ratio
+but saves time since there are both fewer insertions and fewer searches.
+
+
+2. Decompression algorithm (inflate)
+
+2.1 Introduction
+
+The real question is, given a Huffman tree, how to decode fast. The most
+important realization is that shorter codes are much more common than
+longer codes, so pay attention to decoding the short codes fast, and let
+the long codes take longer to decode.
+
+inflate() sets up a first level table that covers some number of bits of
+input less than the length of longest code. It gets that many bits from the
+stream, and looks it up in the table. The table will tell if the next
+code is that many bits or less and how many, and if it is, it will tell
+the value, else it will point to the next level table for which inflate()
+grabs more bits and tries to decode a longer code.
+
+How many bits to make the first lookup is a tradeoff between the time it
+takes to decode and the time it takes to build the table. If building the
+table took no time (and if you had infinite memory), then there would only
+be a first level table to cover all the way to the longest code. However,
+building the table ends up taking a lot longer for more bits since short
+codes are replicated many times in such a table. What inflate() does is
+simply to make the number of bits in the first table a variable, and set it
+for the maximum speed.
+
+inflate() sends new trees relatively often, so it is possibly set for a
+smaller first level table than an application that has only one tree for
+all the data. For inflate, which has 286 possible codes for the
+literal/length tree, the size of the first table is nine bits. Also the
+distance trees have 30 possible values, and the size of the first table is
+six bits. Note that for each of those cases, the table ended up one bit
+longer than the ``average'' code length, i.e. the code length of an
+approximately flat code which would be a little more than eight bits for
+286 symbols and a little less than five bits for 30 symbols. It would be
+interesting to see if optimizing the first level table for other
+applications gave values within a bit or two of the flat code size.
+
+
+2.2 More details on the inflate table lookup
+
+Ok, you want to know what this cleverly obfuscated inflate tree actually
+looks like. You are correct that it's not a Huffman tree. It is simply a
+lookup table for the first, let's say, nine bits of a Huffman symbol. The
+symbol could be as short as one bit or as long as 15 bits. If a particular
+symbol is shorter than nine bits, then that symbol's translation is duplicated
+in all those entries that start with that symbol's bits. For example, if the
+symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a
+symbol is nine bits long, it appears in the table once.
+
+If the symbol is longer than nine bits, then that entry in the table points
+to another similar table for the remaining bits. Again, there are duplicated
+entries as needed. The idea is that most of the time the symbol will be short
+and there will only be one table look up. (That's whole idea behind data
+compression in the first place.) For the less frequent long symbols, there
+will be two lookups. If you had a compression method with really long
+symbols, you could have as many levels of lookups as is efficient. For
+inflate, two is enough.
+
+So a table entry either points to another table (in which case nine bits in
+the above example are gobbled), or it contains the translation for the symbol
+and the number of bits to gobble. Then you start again with the next
+ungobbled bit.
+
+You may wonder: why not just have one lookup table for how ever many bits the
+longest symbol is? The reason is that if you do that, you end up spending
+more time filling in duplicate symbol entries than you do actually decoding.
+At least for deflate's output that generates new trees every several 10's of
+kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code
+would take too long if you're only decoding several thousand symbols. At the
+other extreme, you could make a new table for every bit in the code. In fact,
+that's essentially a Huffman tree. But then you spend two much time
+traversing the tree while decoding, even for short symbols.
+
+So the number of bits for the first lookup table is a trade of the time to
+fill out the table vs. the time spent looking at the second level and above of
+the table.
+
+Here is an example, scaled down:
+
+The code being decoded, with 10 symbols, from 1 to 6 bits long:
+
+A: 0
+B: 10
+C: 1100
+D: 11010
+E: 11011
+F: 11100
+G: 11101
+H: 11110
+I: 111110
+J: 111111
+
+Let's make the first table three bits long (eight entries):
+
+000: A,1
+001: A,1
+010: A,1
+011: A,1
+100: B,2
+101: B,2
+110: -> table X (gobble 3 bits)
+111: -> table Y (gobble 3 bits)
+
+Each entry is what the bits decode to and how many bits that is, i.e. how
+many bits to gobble. Or the entry points to another table, with the number of
+bits to gobble implicit in the size of the table.
+
+Table X is two bits long since the longest code starting with 110 is five bits
+long:
+
+00: C,1
+01: C,1
+10: D,2
+11: E,2
+
+Table Y is three bits long since the longest code starting with 111 is six
+bits long:
+
+000: F,2
+001: F,2
+010: G,2
+011: G,2
+100: H,2
+101: H,2
+110: I,3
+111: J,3
+
+So what we have here are three tables with a total of 20 entries that had to
+be constructed. That's compared to 64 entries for a single table. Or
+compared to 16 entries for a Huffman tree (six two entry tables and one four
+entry table). Assuming that the code ideally represents the probability of
+the symbols, it takes on the average 1.25 lookups per symbol. That's compared
+to one lookup for the single table, or 1.66 lookups per symbol for the
+Huffman tree.
+
+There, I think that gives you a picture of what's going on. For inflate, the
+meaning of a particular symbol is often more than just a letter. It can be a
+byte (a "literal"), or it can be either a length or a distance which
+indicates a base value and a number of bits to fetch after the code that is
+added to the base value. Or it might be the special end-of-block code. The
+data structures created in inftrees.c try to encode all that information
+compactly in the tables.
+
+
+Jean-loup Gailly Mark Adler
+jloup@gzip.org madler@alumni.caltech.edu
+
+
+References:
+
+[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
+Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
+pp. 337-343.
+
+``DEFLATE Compressed Data Format Specification'' available in
+ftp://ds.internic.net/rfc/rfc1951.txt
diff --git a/cfe/cfe/zlib/compress.c b/cfe/cfe/zlib/compress.c
new file mode 100644
index 0000000..4000959
--- /dev/null
+++ b/cfe/cfe/zlib/compress.c
@@ -0,0 +1,68 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: compress.c,v 1.1 2001/11/09 01:48:01 mpl Exp $ */
+
+#include "zlib.h"
+
+/* ===========================================================================
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least 0.1% larger than sourceLen plus
+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+ int level;
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+#ifdef MAXSEG_64K
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+#endif
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ err = deflateInit(&stream, level);
+ if (err != Z_OK) return err;
+
+ err = deflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ deflateEnd(&stream);
+ return err == Z_OK ? Z_BUF_ERROR : err;
+ }
+ *destLen = stream.total_out;
+
+ err = deflateEnd(&stream);
+ return err;
+}
+
+/* ===========================================================================
+ */
+int ZEXPORT compress (dest, destLen, source, sourceLen)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+{
+ return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
+}
diff --git a/cfe/cfe/zlib/configure b/cfe/cfe/zlib/configure
new file mode 100755
index 0000000..e894235
--- /dev/null
+++ b/cfe/cfe/zlib/configure
@@ -0,0 +1,212 @@
+#!/bin/sh
+# configure script for zlib. This script is needed only if
+# you wish to build a shared library and your system supports them,
+# of if you need special compiler, flags or install directory.
+# Otherwise, you can just use directly "make test; make install"
+#
+# To create a shared library, use "configure --shared"; by default a static
+# library is created. If the primitive shared library support provided here
+# does not work, use ftp://prep.ai.mit.edu/pub/gnu/libtool-*.tar.gz
+#
+# To impose specific compiler or flags or install directory, use for example:
+# prefix=$HOME CC=cc CFLAGS="-O4" ./configure
+# or for csh/tcsh users:
+# (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure)
+# LDSHARED is the command to be used to create a shared library
+
+# Incorrect settings of CC or CFLAGS may prevent creating a shared library.
+# If you have problems, try without defining CC and CFLAGS before reporting
+# an error.
+
+LIBS=libz.a
+SHAREDLIB=libz.so
+VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`
+AR=${AR-"ar rc"}
+RANLIB=${RANLIB-"ranlib"}
+prefix=${prefix-/usr/local}
+exec_prefix=${exec_prefix-'${prefix}'}
+libdir=${libdir-'${exec_prefix}/lib'}
+includedir=${includedir-'${prefix}/include'}
+shared_ext='.so'
+shared=0
+gcc=0
+old_cc="$CC"
+old_cflags="$CFLAGS"
+
+while test $# -ge 1
+do
+case "$1" in
+ -h* | --h*)
+ echo 'usage:'
+ echo ' configure [--shared] [--prefix=PREFIX] [--exec_prefix=EXPREFIX]'
+ echo ' [--libdir=LIBDIR] [--includedir=INCLUDEDIR]'
+ exit 0;;
+ -p*=* | --p*=*) prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
+ -e*=* | --e*=*) exec_prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
+ -l*=* | --libdir=*) libdir=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
+ -i*=* | --includedir=*) includedir=`echo $1 | sed 's/[-a-z_]*=//'`;shift;;
+ -p* | --p*) prefix="$2"; shift; shift;;
+ -e* | --e*) exec_prefix="$2"; shift; shift;;
+ -l* | --l*) libdir="$2"; shift; shift;;
+ -i* | --i*) includedir="$2"; shift; shift;;
+ -s* | --s*) shared=1; shift;;
+ esac
+done
+
+test=ztest$$
+cat > $test.c <<EOF
+extern int getchar();
+int hello() {return getchar();}
+EOF
+
+test -z "$CC" && echo Checking for gcc...
+cc=${CC-gcc}
+cflags=${CFLAGS-"-O3"}
+# to force the asm version use: CFLAGS="-O3 -DASMV" ./configure
+case "$cc" in
+ *gcc*) gcc=1;;
+esac
+
+if test "$gcc" -eq 1 && ($cc -c $cflags $test.c) 2>/dev/null; then
+ CC="$cc"
+ SFLAGS=${CFLAGS-"-fPIC -O3"}
+ CFLAGS="$cflags"
+ case `(uname -s || echo unknown) 2>/dev/null` in
+ Linux | linux) LDSHARED=${LDSHARED-"gcc -shared -Wl,-soname,libz.so.1"};;
+ *) LDSHARED=${LDSHARED-"gcc -shared"};;
+ esac
+else
+ # find system name and corresponding cc options
+ CC=${CC-cc}
+ case `(uname -sr || echo unknown) 2>/dev/null` in
+ HP-UX*) SFLAGS=${CFLAGS-"-O +z"}
+ CFLAGS=${CFLAGS-"-O"}
+# LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"}
+ LDSHARED=${LDSHARED-"ld -b"}
+ shared_ext='.sl'
+ SHAREDLIB='libz.sl';;
+ IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."}
+ CFLAGS=${CFLAGS-"-ansi -O2"}
+ LDSHARED=${LDSHARED-"cc -shared"};;
+ OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"}
+ CFLAGS=${CFLAGS-"-O -std1"}
+ LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,$SHAREDLIB -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"};;
+ OSF1*) SFLAGS=${CFLAGS-"-O -std1"}
+ CFLAGS=${CFLAGS-"-O -std1"}
+ LDSHARED=${LDSHARED-"cc -shared"};;
+ QNX*) SFLAGS=${CFLAGS-"-4 -O"}
+ CFLAGS=${CFLAGS-"-4 -O"}
+ LDSHARED=${LDSHARED-"cc"}
+ RANLIB=${RANLIB-"true"}
+ AR="cc -A";;
+ SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "}
+ CFLAGS=${CFLAGS-"-O3"}
+ LDSHARED=${LDSHARED-"cc -dy -KPIC -G"};;
+ SunOS\ 5*) SFLAGS=${CFLAGS-"-fast -xcg89 -KPIC -R."}
+ CFLAGS=${CFLAGS-"-fast -xcg89"}
+ LDSHARED=${LDSHARED-"cc -G"};;
+ SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"}
+ CFLAGS=${CFLAGS-"-O2"}
+ LDSHARED=${LDSHARED-"ld"};;
+ UNIX_System_V\ 4.2.0)
+ SFLAGS=${CFLAGS-"-KPIC -O"}
+ CFLAGS=${CFLAGS-"-O"}
+ LDSHARED=${LDSHARED-"cc -G"};;
+ UNIX_SV\ 4.2MP)
+ SFLAGS=${CFLAGS-"-Kconform_pic -O"}
+ CFLAGS=${CFLAGS-"-O"}
+ LDSHARED=${LDSHARED-"cc -G"};;
+ # send working options for other systems to support@gzip.org
+ *) SFLAGS=${CFLAGS-"-O"}
+ CFLAGS=${CFLAGS-"-O"}
+ LDSHARED=${LDSHARED-"cc -shared"};;
+ esac
+fi
+
+if test $shared -eq 1; then
+ echo Checking for shared library support...
+ # we must test in two steps (cc then ld), required at least on SunOS 4.x
+ if test "`($CC -c $SFLAGS $test.c) 2>&1`" = "" &&
+ test "`($LDSHARED -o $test$shared_ext $test.o) 2>&1`" = ""; then
+ CFLAGS="$SFLAGS"
+ LIBS="$SHAREDLIB.$VER"
+ echo Building shared library $SHAREDLIB.$VER with $CC.
+ elif test -z "$old_cc" -a -z "$old_cflags"; then
+ echo No shared library suppport.
+ shared=0;
+ else
+ echo 'No shared library suppport; try without defining CC and CFLAGS'
+ shared=0;
+ fi
+fi
+if test $shared -eq 0; then
+ LDSHARED="$CC"
+ echo Building static library $LIBS version $VER with $CC.
+fi
+
+cat > $test.c <<EOF
+#include <unistd.h>
+int main() { return 0; }
+EOF
+if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+ CFLAGS="$CFLAGS -DHAVE_UNISTD_H"
+ echo "Checking for unistd.h... Yes."
+else
+ echo "Checking for unistd.h... No."
+fi
+
+cat > $test.c <<EOF
+#include <errno.h>
+int main() { return 0; }
+EOF
+if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+ echo "Checking for errno.h... Yes."
+else
+ echo "Checking for errno.h... No."
+ CFLAGS="$CFLAGS -DNO_ERRNO_H"
+fi
+
+cat > $test.c <<EOF
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+caddr_t hello() {
+ return mmap((caddr_t)0, (off_t)0, PROT_READ, MAP_SHARED, 0, (off_t)0);
+}
+EOF
+if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+ CFLAGS="$CFLAGS -DUSE_MMAP"
+ echo Checking for mmap support... Yes.
+else
+ echo Checking for mmap support... No.
+fi
+
+CPP=${CPP-"$CC -E"}
+case $CFLAGS in
+ *ASMV*)
+ if test "`nm $test.o | grep _hello`" = ""; then
+ CPP="$CPP -DNO_UNDERLINE"
+ echo Checking for underline in external names... No.
+ else
+ echo Checking for underline in external names... Yes.
+ fi;;
+esac
+
+rm -f $test.[co] $test$shared_ext
+
+# udpate Makefile
+sed < Makefile.in "
+/^CC *=/s%=.*%=$CC%
+/^CFLAGS *=/s%=.*%=$CFLAGS%
+/^CPP *=/s%=.*%=$CPP%
+/^LDSHARED *=/s%=.*%=$LDSHARED%
+/^LIBS *=/s%=.*%=$LIBS%
+/^SHAREDLIB *=/s%=.*%=$SHAREDLIB%
+/^AR *=/s%=.*%=$AR%
+/^RANLIB *=/s%=.*%=$RANLIB%
+/^VER *=/s%=.*%=$VER%
+/^prefix *=/s%=.*%=$prefix%
+/^exec_prefix *=/s%=.*%=$exec_prefix%
+/^libdir *=/s%=.*%=$libdir%
+/^includedir *=/s%=.*%=$includedir%
+" > Makefile
diff --git a/cfe/cfe/zlib/crc32.c b/cfe/cfe/zlib/crc32.c
new file mode 100644
index 0000000..0402f67
--- /dev/null
+++ b/cfe/cfe/zlib/crc32.c
@@ -0,0 +1,162 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: crc32.c,v 1.1 2001/11/09 01:48:01 mpl Exp $ */
+
+#include "zlib.h"
+
+#define local static
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local int crc_table_empty = 1;
+local uLongf crc_table[256];
+local void make_crc_table OF((void));
+
+/*
+ Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
+ x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+ Polynomials over GF(2) are represented in binary, one bit per coefficient,
+ with the lowest powers in the most significant bit. Then adding polynomials
+ is just exclusive-or, and multiplying a polynomial by x is a right shift by
+ one. If we call the above polynomial p, and represent a byte as the
+ polynomial q, also with the lowest power in the most significant bit (so the
+ byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+ where a mod b means the remainder after dividing a by b.
+
+ This calculation is done using the shift-register method of multiplying and
+ taking the remainder. The register is initialized to zero, and for each
+ incoming bit, x^32 is added mod p to the register if the bit is a one (where
+ x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+ x (which is shifting right by one and adding x^32 mod p if the bit shifted
+ out is a one). We start with the highest power (least significant bit) of
+ q and repeat for all eight bits of q.
+
+ The table is simply the CRC of all possible eight bit values. This is all
+ the information needed to generate CRC's on data a byte at a time for all
+ combinations of CRC register values and incoming bytes.
+*/
+local void make_crc_table()
+{
+ uLong c;
+ int n, k;
+ uLong poly; /* polynomial exclusive-or pattern */
+ /* terms of polynomial defining this crc (except x^32): */
+ static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+ /* make exclusive-or pattern from polynomial (0xedb88320L) */
+ poly = 0L;
+ for (n = 0; n < sizeof(p)/sizeof(Byte); n++)
+ poly |= 1L << (31 - p[n]);
+
+ for (n = 0; n < 256; n++)
+ {
+ c = (uLong)n;
+ for (k = 0; k < 8; k++)
+ c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+ crc_table[n] = c;
+ }
+ crc_table_empty = 0;
+}
+#else
+/* ========================================================================
+ * Table of CRC-32's of all single-byte values (made by make_crc_table)
+ */
+local const uLongf crc_table[256] = {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+};
+#endif
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+const uLongf * ZEXPORT get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty) make_crc_table();
+#endif
+ return (const uLongf *)crc_table;
+}
+
+/* ========================================================================= */
+#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
+#define DO2(buf) DO1(buf); DO1(buf);
+#define DO4(buf) DO2(buf); DO2(buf);
+#define DO8(buf) DO4(buf); DO4(buf);
+
+/* ========================================================================= */
+uLong ZEXPORT crc32(crc, buf, len)
+ uLong crc;
+ const Bytef *buf;
+ uInt len;
+{
+ if (buf == Z_NULL) return 0L;
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty)
+ make_crc_table();
+#endif
+ crc = crc ^ 0xffffffffL;
+ while (len >= 8)
+ {
+ DO8(buf);
+ len -= 8;
+ }
+ if (len) do {
+ DO1(buf);
+ } while (--len);
+ return crc ^ 0xffffffffL;
+}
diff --git a/cfe/cfe/zlib/deflate.c b/cfe/cfe/zlib/deflate.c
new file mode 100644
index 0000000..be87d40
--- /dev/null
+++ b/cfe/cfe/zlib/deflate.c
@@ -0,0 +1,1350 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process depends on being able to identify portions
+ * of the input text which are identical to earlier input (within a
+ * sliding window trailing behind the input currently being processed).
+ *
+ * The most straightforward technique turns out to be the fastest for
+ * most input files: try all possible matches and select the longest.
+ * The key feature of this algorithm is that insertions into the string
+ * dictionary are very simple and thus fast, and deletions are avoided
+ * completely. Insertions are performed at each input character, whereas
+ * string matches are performed only when the previous match ends. So it
+ * is preferable to spend more time in matches to allow very fast string
+ * insertions and avoid deletions. The matching algorithm for small
+ * strings is inspired from that of Rabin & Karp. A brute force approach
+ * is used to find longer strings when a small match has been found.
+ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ * (by Leonid Broukhis).
+ * A previous version of this file used a more sophisticated algorithm
+ * (by Fiala and Greene) which is guaranteed to run in linear amortized
+ * time, but has a larger average cost, uses more memory and is patented.
+ * However the F&G algorithm may be faster for some highly redundant
+ * files if the parameter max_chain_length (described below) is too large.
+ *
+ * ACKNOWLEDGEMENTS
+ *
+ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ * I found it in 'freeze' written by Leonid Broukhis.
+ * Thanks to many people for bug reports and testing.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ * Available in ftp://ds.internic.net/rfc/rfc1951.txt
+ *
+ * A description of the Rabin and Karp algorithm is given in the book
+ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ * Fiala,E.R., and Greene,D.H.
+ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id: deflate.c,v 1.1 2001/11/09 01:48:02 mpl Exp $ */
+
+#include "deflate.h"
+
+const char deflate_copyright[] =
+ " deflate 1.1.3 Copyright 1995-1998 Jean-loup Gailly ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ * Function prototypes.
+ */
+typedef enum {
+ need_more, /* block not completed, need more input or more output */
+ block_done, /* block flush performed */
+ finish_started, /* finish started, need only more output at next deflate */
+ finish_done /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local void fill_window OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast OF((deflate_state *s, int flush));
+local block_state deflate_slow OF((deflate_state *s, int flush));
+local void lm_init OF((deflate_state *s));
+local void putShortMSB OF((deflate_state *s, uInt b));
+local void flush_pending OF((z_streamp strm));
+local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size));
+#ifdef ASMV
+ void match_init OF((void)); /* asm code initialization */
+ uInt longest_match OF((deflate_state *s, IPos cur_match));
+#else
+local uInt longest_match OF((deflate_state *s, IPos cur_match));
+#endif
+
+#ifdef DEBUG
+local void check_match OF((deflate_state *s, IPos start, IPos match,
+ int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+# define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+ ush good_length; /* reduce lazy search above this match length */
+ ush max_lazy; /* do not perform lazy search above this match length */
+ ush nice_length; /* quit search above this match length */
+ ush max_chain;
+ compress_func func;
+} config;
+
+local const config configuration_table[10] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */
+/* 2 */ {4, 5, 16, 8, deflate_fast},
+/* 3 */ {4, 6, 32, 32, deflate_fast},
+
+/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */
+/* 5 */ {8, 16, 32, 32, deflate_slow},
+/* 6 */ {8, 16, 128, 128, deflate_slow},
+/* 7 */ {8, 32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN assertion: all calls to to UPDATE_HASH are made with consecutive
+ * input characters, so that a running hash key can be computed from the
+ * previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN assertion: all calls to to INSERT_STRING are made with consecutive
+ * input characters and the first MIN_MATCH bytes of str are valid
+ * (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+ s->head[s->hash_size-1] = NIL; \
+ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(strm, level, version, stream_size)
+ z_streamp strm;
+ int level;
+ const char *version;
+ int stream_size;
+{
+ return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY, version, stream_size);
+ /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+ version, stream_size)
+ z_streamp strm;
+ int level;
+ int method;
+ int windowBits;
+ int memLevel;
+ int strategy;
+ const char *version;
+ int stream_size;
+{
+ deflate_state *s;
+ int noheader = 0;
+ static const char* my_version = ZLIB_VERSION;
+
+ ushf *overlay;
+ /* We overlay pending_buf and d_buf+l_buf. This works since the average
+ * output size for (length,distance) codes is <= 24 bits.
+ */
+
+ if (version == Z_NULL || version[0] != my_version[0] ||
+ stream_size != sizeof(z_stream)) {
+ return Z_VERSION_ERROR;
+ }
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+ strm->msg = Z_NULL;
+ if (strm->zalloc == Z_NULL) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == Z_NULL) strm->zfree = zcfree;
+
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#ifdef FASTEST
+ level = 1;
+#endif
+
+ if (windowBits < 0) { /* undocumented feature: suppress zlib header */
+ noheader = 1;
+ windowBits = -windowBits;
+ }
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+ windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+ strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
+ return Z_STREAM_ERROR;
+ }
+ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+ if (s == Z_NULL) return Z_MEM_ERROR;
+ strm->state = (struct internal_state FAR *)s;
+ s->strm = strm;
+
+ s->noheader = noheader;
+ s->w_bits = windowBits;
+ s->w_size = 1 << s->w_bits;
+ s->w_mask = s->w_size - 1;
+
+ s->hash_bits = memLevel + 7;
+ s->hash_size = 1 << s->hash_bits;
+ s->hash_mask = s->hash_size - 1;
+ s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+ s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+ s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
+ s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+ s->pending_buf = (uchf *) overlay;
+ s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+
+ if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+ s->pending_buf == Z_NULL) {
+ strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+ deflateEnd (strm);
+ return Z_MEM_ERROR;
+ }
+ s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+ s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+ s->level = level;
+ s->strategy = strategy;
+ s->method = (Byte)method;
+
+ return deflateReset(strm);
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
+ z_streamp strm;
+ const Bytef *dictionary;
+ uInt dictLength;
+{
+ deflate_state *s;
+ uInt length = dictLength;
+ uInt n;
+ IPos hash_head = 0;
+
+ if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
+ strm->state->status != INIT_STATE) return Z_STREAM_ERROR;
+
+ s = strm->state;
+ strm->adler = adler32(strm->adler, dictionary, dictLength);
+
+ if (length < MIN_MATCH) return Z_OK;
+ if (length > MAX_DIST(s)) {
+ length = MAX_DIST(s);
+#ifndef USE_DICT_HEAD
+ dictionary += dictLength - length; /* use the tail of the dictionary */
+#endif
+ }
+ zmemcpy(s->window, dictionary, length);
+ s->strstart = length;
+ s->block_start = (long)length;
+
+ /* Insert all strings in the hash table (except for the last two bytes).
+ * s->lookahead stays null, so s->ins_h will be recomputed at the next
+ * call of fill_window.
+ */
+ s->ins_h = s->window[0];
+ UPDATE_HASH(s, s->ins_h, s->window[1]);
+ for (n = 0; n <= length - MIN_MATCH; n++) {
+ INSERT_STRING(s, n, hash_head);
+ }
+ if (hash_head) hash_head = 0; /* to make compiler happy */
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset (strm)
+ z_streamp strm;
+{
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR;
+
+ strm->total_in = strm->total_out = 0;
+ strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+ strm->data_type = Z_UNKNOWN;
+
+ s = (deflate_state *)strm->state;
+ s->pending = 0;
+ s->pending_out = s->pending_buf;
+
+ if (s->noheader < 0) {
+ s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */
+ }
+ s->status = s->noheader ? BUSY_STATE : INIT_STATE;
+ strm->adler = 1;
+ s->last_flush = Z_NO_FLUSH;
+
+ _tr_init(s);
+ lm_init(s);
+
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(strm, level, strategy)
+ z_streamp strm;
+ int level;
+ int strategy;
+{
+ deflate_state *s;
+ compress_func func;
+ int err = Z_OK;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = strm->state;
+
+ if (level == Z_DEFAULT_COMPRESSION) {
+ level = 6;
+ }
+ if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
+ return Z_STREAM_ERROR;
+ }
+ func = configuration_table[s->level].func;
+
+ if (func != configuration_table[level].func && strm->total_in != 0) {
+ /* Flush the last buffer: */
+ err = deflate(strm, Z_PARTIAL_FLUSH);
+ }
+ if (s->level != level) {
+ s->level = level;
+ s->max_lazy_match = configuration_table[level].max_lazy;
+ s->good_match = configuration_table[level].good_length;
+ s->nice_match = configuration_table[level].nice_length;
+ s->max_chain_length = configuration_table[level].max_chain;
+ }
+ s->strategy = strategy;
+ return err;
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (s, b)
+ deflate_state *s;
+ uInt b;
+{
+ put_byte(s, (Byte)(b >> 8));
+ put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+local void flush_pending(strm)
+ z_streamp strm;
+{
+ unsigned len = strm->state->pending;
+
+ if (len > strm->avail_out) len = strm->avail_out;
+ if (len == 0) return;
+
+ zmemcpy(strm->next_out, strm->state->pending_out, len);
+ strm->next_out += len;
+ strm->state->pending_out += len;
+ strm->total_out += len;
+ strm->avail_out -= len;
+ strm->state->pending -= len;
+ if (strm->state->pending == 0) {
+ strm->state->pending_out = strm->state->pending_buf;
+ }
+}
+
+/* ========================================================================= */
+int ZEXPORT deflate (strm, flush)
+ z_streamp strm;
+ int flush;
+{
+ int old_flush; /* value of flush param for previous deflate call */
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ flush > Z_FINISH || flush < 0) {
+ return Z_STREAM_ERROR;
+ }
+ s = strm->state;
+
+ if (strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0) ||
+ (s->status == FINISH_STATE && flush != Z_FINISH)) {
+ ERR_RETURN(strm, Z_STREAM_ERROR);
+ }
+ if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+ s->strm = strm; /* just in case */
+ old_flush = s->last_flush;
+ s->last_flush = flush;
+
+ /* Write the zlib header */
+ if (s->status == INIT_STATE) {
+
+ uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+ uInt level_flags = (s->level-1) >> 1;
+
+ if (level_flags > 3) level_flags = 3;
+ header |= (level_flags << 6);
+ if (s->strstart != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ s->status = BUSY_STATE;
+ putShortMSB(s, header);
+
+ /* Save the adler32 of the preset dictionary: */
+ if (s->strstart != 0) {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ strm->adler = 1L;
+ }
+
+ /* Flush as much pending output as possible */
+ if (s->pending != 0) {
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ /* Since avail_out is 0, deflate will be called again with
+ * more output space, but possibly with both pending and
+ * avail_in equal to zero. There won't be anything to do,
+ * but this is not an error situation so make sure we
+ * return OK instead of BUF_ERROR at next call of deflate:
+ */
+ s->last_flush = -1;
+ return Z_OK;
+ }
+
+ /* Make sure there is something to do and avoid duplicate consecutive
+ * flushes. For repeated and useless calls with Z_FINISH, we keep
+ * returning Z_STREAM_END instead of Z_BUFF_ERROR.
+ */
+ } else if (strm->avail_in == 0 && flush <= old_flush &&
+ flush != Z_FINISH) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* User must not provide more input after the first FINISH: */
+ if (s->status == FINISH_STATE && strm->avail_in != 0) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* Start a new block or continue the current one.
+ */
+ if (strm->avail_in != 0 || s->lookahead != 0 ||
+ (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+ block_state bstate;
+
+ bstate = (*(configuration_table[s->level].func))(s, flush);
+
+ if (bstate == finish_started || bstate == finish_done) {
+ s->status = FINISH_STATE;
+ }
+ if (bstate == need_more || bstate == finish_started) {
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+ }
+ return Z_OK;
+ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ * of deflate should use the same flush parameter to make sure
+ * that the flush is complete. So we don't have to output an
+ * empty block here, this will be done at next call. This also
+ * ensures that for a very small output buffer, we emit at most
+ * one empty block.
+ */
+ }
+ if (bstate == block_done) {
+ if (flush == Z_PARTIAL_FLUSH) {
+ _tr_align(s);
+ } else { /* FULL_FLUSH or SYNC_FLUSH */
+ _tr_stored_block(s, (char*)0, 0L, 0);
+ /* For a full flush, this empty block will be recognized
+ * as a special marker by inflate_sync().
+ */
+ if (flush == Z_FULL_FLUSH) {
+ CLEAR_HASH(s); /* forget history */
+ }
+ }
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+ return Z_OK;
+ }
+ }
+ }
+ Assert(strm->avail_out > 0, "bug2");
+
+ if (flush != Z_FINISH) return Z_OK;
+ if (s->noheader) return Z_STREAM_END;
+
+ /* Write the zlib trailer (adler32) */
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ flush_pending(strm);
+ /* If avail_out is zero, the application will call deflate again
+ * to flush the rest.
+ */
+ s->noheader = -1; /* write the trailer only once! */
+ return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd (strm)
+ z_streamp strm;
+{
+ int status;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+
+ status = strm->state->status;
+ if (status != INIT_STATE && status != BUSY_STATE &&
+ status != FINISH_STATE) {
+ return Z_STREAM_ERROR;
+ }
+
+ /* Deallocate in reverse order of allocations: */
+ TRY_FREE(strm, strm->state->pending_buf);
+ TRY_FREE(strm, strm->state->head);
+ TRY_FREE(strm, strm->state->prev);
+ TRY_FREE(strm, strm->state->window);
+
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+
+ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy (dest, source)
+ z_streamp dest;
+ z_streamp source;
+{
+#ifdef MAXSEG_64K
+ return Z_STREAM_ERROR;
+#else
+ deflate_state *ds;
+ deflate_state *ss;
+ ushf *overlay;
+
+
+ if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
+ return Z_STREAM_ERROR;
+ }
+
+ ss = source->state;
+
+ *dest = *source;
+
+ ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+ if (ds == Z_NULL) return Z_MEM_ERROR;
+ dest->state = (struct internal_state FAR *) ds;
+ *ds = *ss;
+ ds->strm = dest;
+
+ ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+ ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
+ ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
+ overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
+ ds->pending_buf = (uchf *) overlay;
+
+ if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+ ds->pending_buf == Z_NULL) {
+ deflateEnd (dest);
+ return Z_MEM_ERROR;
+ }
+ /* following zmemcpy do not work for 16-bit MSDOS */
+ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+ zmemcpy((Bytef *) ds->prev, (const Bytef *) ss->prev, ds->w_size * sizeof(Pos));
+ zmemcpy((Bytef *) ds->head, (const Bytef *) ss->head, ds->hash_size * sizeof(Pos));
+ zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+ ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+ ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
+ ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+
+ ds->l_desc.dyn_tree = ds->dyn_ltree;
+ ds->d_desc.dyn_tree = ds->dyn_dtree;
+ ds->bl_desc.dyn_tree = ds->bl_tree;
+
+ return Z_OK;
+#endif
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read. All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local int read_buf(strm, buf, size)
+ z_streamp strm;
+ Bytef *buf;
+ unsigned size;
+{
+ unsigned len = strm->avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ strm->avail_in -= len;
+
+ if (!strm->state->noheader) {
+ strm->adler = adler32(strm->adler, strm->next_in, len);
+ }
+ zmemcpy(buf, strm->next_in, len);
+ strm->next_in += len;
+ strm->total_in += len;
+
+ return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (s)
+ deflate_state *s;
+{
+ s->window_size = (ulg)2L*s->w_size;
+
+ CLEAR_HASH(s);
+
+ /* Set the default configuration parameters:
+ */
+ s->max_lazy_match = configuration_table[s->level].max_lazy;
+ s->good_match = configuration_table[s->level].good_length;
+ s->nice_match = configuration_table[s->level].nice_length;
+ s->max_chain_length = configuration_table[s->level].max_chain;
+
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->lookahead = 0;
+ s->match_length = s->prev_length = MIN_MATCH-1;
+ s->match_available = 0;
+ s->ins_h = 0;
+#ifdef ASMV
+ match_init(); /* initialize the asm code */
+#endif
+}
+
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+#ifndef FASTEST
+local uInt longest_match(s, cur_match)
+ deflate_state *s;
+ IPos cur_match; /* current match */
+{
+ unsigned chain_length = s->max_chain_length;/* max hash chain length */
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ int best_len = s->prev_length; /* best match length so far */
+ int nice_match = s->nice_match; /* stop if match long enough */
+ IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+ s->strstart - (IPos)MAX_DIST(s) : NIL;
+ /* Stop when cur_match becomes <= limit. To simplify the code,
+ * we prevent matches with the string of window index 0.
+ */
+ Posf *prev = s->prev;
+ uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+ /* Compare two bytes at a time. Note: this is not always beneficial.
+ * Try with and without -DUNALIGNED_OK to check.
+ */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+ register ush scan_start = *(ushf*)scan;
+ register ush scan_end = *(ushf*)(scan+best_len-1);
+#else
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+ register Byte scan_end1 = scan[best_len-1];
+ register Byte scan_end = scan[best_len];
+#endif
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ /* Do not waste too much time if we already have a good match: */
+ if (s->prev_length >= s->good_match) {
+ chain_length >>= 2;
+ }
+ /* Do not look for matches beyond the end of the input. This is necessary
+ * to make deflate deterministic.
+ */
+ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ do {
+ Assert(cur_match < s->strstart, "no future");
+ match = s->window + cur_match;
+
+ /* Skip to next match if the match length cannot increase
+ * or if the match length is less than 2:
+ */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+ /* This code assumes sizeof(unsigned short) == 2. Do not use
+ * UNALIGNED_OK if your compiler uses a different size.
+ */
+ if (*(ushf*)(match+best_len-1) != scan_end ||
+ *(ushf*)match != scan_start) continue;
+
+ /* It is not necessary to compare scan[2] and match[2] since they are
+ * always equal when the other bytes match, given that the hash keys
+ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+ * strstart+3, +5, ... up to strstart+257. We check for insufficient
+ * lookahead only every 4th comparison; the 128th check will be made
+ * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+ * necessary to put more guard bytes at the end of the window, or
+ * to check more often for insufficient lookahead.
+ */
+ Assert(scan[2] == match[2], "scan[2]?");
+ scan++, match++;
+ do {
+ } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ scan < strend);
+ /* The funny "do {}" generates better code on most compilers */
+
+ /* Here, scan <= window+strstart+257 */
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+ if (*scan == *match) scan++;
+
+ len = (MAX_MATCH - 1) - (int)(strend-scan);
+ scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+ if (match[best_len] != scan_end ||
+ match[best_len-1] != scan_end1 ||
+ *match != *scan ||
+ *++match != scan[1]) continue;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match++;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+ if (len > best_len) {
+ s->match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+ scan_end = *(ushf*)(scan+best_len-1);
+#else
+ scan_end1 = scan[best_len-1];
+ scan_end = scan[best_len];
+#endif
+ }
+ } while ((cur_match = prev[cur_match & wmask]) > limit
+ && --chain_length != 0);
+
+ if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+ return s->lookahead;
+}
+
+#else /* FASTEST */
+/* ---------------------------------------------------------------------------
+ * Optimized version for level == 1 only
+ */
+local uInt longest_match(s, cur_match)
+ deflate_state *s;
+ IPos cur_match; /* current match */
+{
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ Assert(cur_match < s->strstart, "no future");
+
+ match = s->window + cur_match;
+
+ /* Return failure if the match length is less than 2:
+ */
+ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match += 2;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+
+ if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+ s->match_start = cur_match;
+ return len <= s->lookahead ? len : s->lookahead;
+}
+#endif /* FASTEST */
+#endif /* ASMV */
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(s, start, match, length)
+ deflate_state *s;
+ IPos start, match;
+ int length;
+{
+ /* check that the match is indeed a match */
+ if (zmemcmp(s->window + match,
+ s->window + start, length) != EQUAL) {
+ fprintf(stderr, " start %u, match %u, length %d\n",
+ start, match, length);
+ do {
+ fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+ } while (--length != 0);
+ z_error("invalid match");
+ }
+ if (z_verbose > 1) {
+ fprintf(stderr,"\\[%d,%d]", start-match, length);
+ do { putc(s->window[start++], stderr); } while (--length != 0);
+ }
+}
+#else
+# define check_match(s, start, match, length)
+#endif
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ * At least one byte has been read, or avail_in == 0; reads are
+ * performed for at least two bytes (required for the zip translate_eol
+ * option -- not supported here).
+ */
+local void fill_window(s)
+ deflate_state *s;
+{
+ register unsigned n, m;
+ register Posf *p;
+ unsigned more; /* Amount of free space at the end of the window. */
+ uInt wsize = s->w_size;
+
+ do {
+ more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+ /* Deal with !@#$% 64K limit: */
+ if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+ more = wsize;
+
+ } else if (more == (unsigned)(-1)) {
+ /* Very unlikely, but possible on 16 bit machine if strstart == 0
+ * and lookahead == 1 (input done one byte at time)
+ */
+ more--;
+
+ /* If the window is almost full and there is insufficient lookahead,
+ * move the upper half to the lower one to make room in the upper half.
+ */
+ } else if (s->strstart >= wsize+MAX_DIST(s)) {
+
+ zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
+ s->match_start -= wsize;
+ s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
+ s->block_start -= (long) wsize;
+
+ /* Slide the hash table (could be avoided with 32 bit values
+ at the expense of memory usage). We slide even when level == 0
+ to keep the hash table consistent if we switch back to level > 0
+ later. (Using level 0 permanently is not an optimal usage of
+ zlib, so we don't care about this pathological case.)
+ */
+ n = s->hash_size;
+ p = &s->head[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ } while (--n);
+
+ n = wsize;
+#ifndef FASTEST
+ p = &s->prev[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ /* If n is not on any hash chain, prev[n] is garbage but
+ * its value will never be used.
+ */
+ } while (--n);
+#endif
+ more += wsize;
+ }
+ if (s->strm->avail_in == 0) return;
+
+ /* If there was no sliding:
+ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ * more == window_size - lookahead - strstart
+ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ * => more >= window_size - 2*WSIZE + 2
+ * In the BIG_MEM or MMAP case (not yet supported),
+ * window_size == input_size + MIN_LOOKAHEAD &&
+ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ * Otherwise, window_size == 2*WSIZE so more >= 2.
+ * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+ */
+ Assert(more >= 2, "more < 2");
+
+ n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+ s->lookahead += n;
+
+ /* Initialize the hash value now that we have some input: */
+ if (s->lookahead >= MIN_MATCH) {
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ }
+ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ * but this is not important since only literal bytes will be emitted.
+ */
+
+ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, eof) { \
+ _tr_flush_block(s, (s->block_start >= 0L ? \
+ (charf *)&s->window[(unsigned)s->block_start] : \
+ (charf *)Z_NULL), \
+ (ulg)((long)s->strstart - s->block_start), \
+ (eof)); \
+ s->block_start = s->strstart; \
+ flush_pending(s->strm); \
+ Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, eof) { \
+ FLUSH_BLOCK_ONLY(s, eof); \
+ if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+local block_state deflate_stored(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ * to pending_buf_size, and each stored block has a 5 byte header:
+ */
+ ulg max_block_size = 0xffff;
+ ulg max_start;
+
+ if (max_block_size > s->pending_buf_size - 5) {
+ max_block_size = s->pending_buf_size - 5;
+ }
+
+ /* Copy as much as possible from input to output: */
+ for (;;) {
+ /* Fill the window as much as possible: */
+ if (s->lookahead <= 1) {
+
+ Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+ s->block_start >= (long)s->w_size, "slide too late");
+
+ fill_window(s);
+ if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+ Assert(s->block_start >= 0L, "block gone");
+
+ s->strstart += s->lookahead;
+ s->lookahead = 0;
+
+ /* Emit a stored block if pending_buf will be full: */
+ max_start = s->block_start + max_block_size;
+ if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
+ /* strstart == 0 is possible when wraparound on 16-bit machine */
+ s->lookahead = (uInt)(s->strstart - max_start);
+ s->strstart = (uInt)max_start;
+ FLUSH_BLOCK(s, 0);
+ }
+ /* Flush if we may have to slide, otherwise block_start may become
+ * negative and the data will be gone:
+ */
+ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+ FLUSH_BLOCK(s, 0);
+ }
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ IPos hash_head = NIL; /* head of the hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ * At this point we have always match_length < MIN_MATCH
+ */
+ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ if (s->strategy != Z_HUFFMAN_ONLY) {
+ s->match_length = longest_match (s, hash_head);
+ }
+ /* longest_match() sets match_start */
+ }
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->match_start, s->match_length);
+
+ _tr_tally_dist(s, s->strstart - s->match_start,
+ s->match_length - MIN_MATCH, bflush);
+
+ s->lookahead -= s->match_length;
+
+ /* Insert new strings in the hash table only if the match length
+ * is not too large. This saves time but degrades compression.
+ */
+#ifndef FASTEST
+ if (s->match_length <= s->max_insert_length &&
+ s->lookahead >= MIN_MATCH) {
+ s->match_length--; /* string at strstart already in hash table */
+ do {
+ s->strstart++;
+ INSERT_STRING(s, s->strstart, hash_head);
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead.
+ */
+ } while (--s->match_length != 0);
+ s->strstart++;
+ } else
+#endif
+ {
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ * matter since it will be recomputed at next deflate call.
+ */
+ }
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit (s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ IPos hash_head = NIL; /* head of hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ /* Process the input block. */
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ */
+ s->prev_length = s->match_length, s->prev_match = s->match_start;
+ s->match_length = MIN_MATCH-1;
+
+ if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+ s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ if (s->strategy != Z_HUFFMAN_ONLY) {
+ s->match_length = longest_match (s, hash_head);
+ }
+ /* longest_match() sets match_start */
+
+ if (s->match_length <= 5 && (s->strategy == Z_FILTERED ||
+ (s->match_length == MIN_MATCH &&
+ s->strstart - s->match_start > TOO_FAR))) {
+
+ /* If prev_match is also MIN_MATCH, match_start is garbage
+ * but we will ignore the current match anyway.
+ */
+ s->match_length = MIN_MATCH-1;
+ }
+ }
+ /* If there was a match at the previous step and the current
+ * match is not better, output the previous match:
+ */
+ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+ uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+ /* Do not insert strings in hash table beyond this. */
+
+ check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+ _tr_tally_dist(s, s->strstart -1 - s->prev_match,
+ s->prev_length - MIN_MATCH, bflush);
+
+ /* Insert in hash table all strings up to the end of the match.
+ * strstart-1 and strstart are already inserted. If there is not
+ * enough lookahead, the last two strings are not inserted in
+ * the hash table.
+ */
+ s->lookahead -= s->prev_length-1;
+ s->prev_length -= 2;
+ do {
+ if (++s->strstart <= max_insert) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+ } while (--s->prev_length != 0);
+ s->match_available = 0;
+ s->match_length = MIN_MATCH-1;
+ s->strstart++;
+
+ if (bflush) FLUSH_BLOCK(s, 0);
+
+ } else if (s->match_available) {
+ /* If there was no match at the previous position, output a
+ * single literal. If there was a match but the current match
+ * is longer, truncate the previous match to a single literal.
+ */
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+ if (bflush) {
+ FLUSH_BLOCK_ONLY(s, 0);
+ }
+ s->strstart++;
+ s->lookahead--;
+ if (s->strm->avail_out == 0) return need_more;
+ } else {
+ /* There is no previous match to compare with, wait for
+ * the next step to decide.
+ */
+ s->match_available = 1;
+ s->strstart++;
+ s->lookahead--;
+ }
+ }
+ Assert (flush != Z_NO_FLUSH, "no flush?");
+ if (s->match_available) {
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+ s->match_available = 0;
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
diff --git a/cfe/cfe/zlib/deflate.h b/cfe/cfe/zlib/deflate.h
new file mode 100644
index 0000000..e91a4f2
--- /dev/null
+++ b/cfe/cfe/zlib/deflate.h
@@ -0,0 +1,318 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-1998 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id: deflate.h,v 1.1 2001/11/09 01:48:02 mpl Exp $ */
+
+#ifndef _DEFLATE_H
+#define _DEFLATE_H
+
+#include "zutil.h"
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS 256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES 30
+/* number of distance codes */
+
+#define BL_CODES 19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE 42
+#define BUSY_STATE 113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+ union {
+ ush freq; /* frequency count */
+ ush code; /* bit string */
+ } fc;
+ union {
+ ush dad; /* father node in Huffman tree */
+ ush len; /* length of bit string */
+ } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad dl.dad
+#define Len dl.len
+
+typedef struct static_tree_desc_s static_tree_desc;
+
+typedef struct tree_desc_s {
+ ct_data *dyn_tree; /* the dynamic tree */
+ int max_code; /* largest code with non zero frequency */
+ static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ int status; /* as the name implies */
+ Bytef *pending_buf; /* output still pending */
+ ulg pending_buf_size; /* size of pending_buf */
+ Bytef *pending_out; /* next pending byte to output to the stream */
+ int pending; /* nb of bytes in the pending buffer */
+ int noheader; /* suppress zlib header and adler32 */
+ Byte data_type; /* UNKNOWN, BINARY or ASCII */
+ Byte method; /* STORED (for zip only) or DEFLATED */
+ int last_flush; /* value of flush param for previous deflate call */
+
+ /* used by deflate.c: */
+
+ uInt w_size; /* LZ77 window size (32K by default) */
+ uInt w_bits; /* log2(w_size) (8..16) */
+ uInt w_mask; /* w_size - 1 */
+
+ Bytef *window;
+ /* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least wSize
+ * bytes. With this organization, matches are limited to a distance of
+ * wSize-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: use the user input buffer as sliding window.
+ */
+
+ ulg window_size;
+ /* Actual size of window: 2*wSize, except when the user input buffer
+ * is directly used as sliding window.
+ */
+
+ Posf *prev;
+ /* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+ Posf *head; /* Heads of the hash chains or NIL. */
+
+ uInt ins_h; /* hash index of string to be inserted */
+ uInt hash_size; /* number of elements in hash table */
+ uInt hash_bits; /* log2(hash_size) */
+ uInt hash_mask; /* hash_size-1 */
+
+ uInt hash_shift;
+ /* Number of bits by which ins_h must be shifted at each input
+ * step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * hash_shift * MIN_MATCH >= hash_bits
+ */
+
+ long block_start;
+ /* Window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+ uInt match_length; /* length of best match */
+ IPos prev_match; /* previous match */
+ int match_available; /* set if previous match exists */
+ uInt strstart; /* start of string to insert */
+ uInt match_start; /* start of matching string */
+ uInt lookahead; /* number of valid bytes ahead in window */
+
+ uInt prev_length;
+ /* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ uInt max_chain_length;
+ /* To speed up deflation, hash chains are never searched beyond this
+ * length. A higher limit improves compression ratio but degrades the
+ * speed.
+ */
+
+ uInt max_lazy_match;
+ /* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+# define max_insert_length max_lazy_match
+ /* Insert new strings in the hash table only if the match length is not
+ * greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+ int level; /* compression level (1..9) */
+ int strategy; /* favor or force Huffman coding*/
+
+ uInt good_match;
+ /* Use a faster search when the previous match is longer than this */
+
+ int nice_match; /* Stop searching when current match exceeds this */
+
+ /* used by trees.c: */
+ /* Didn't use ct_data typedef below to supress compiler warning */
+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
+
+ struct tree_desc_s l_desc; /* desc. for literal tree */
+ struct tree_desc_s d_desc; /* desc. for distance tree */
+ struct tree_desc_s bl_desc; /* desc. for bit length tree */
+
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+ int heap_len; /* number of elements in the heap */
+ int heap_max; /* element of largest frequency */
+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+ uch depth[2*L_CODES+1];
+ /* Depth of each subtree used as tie breaker for trees of equal frequency
+ */
+
+ uchf *l_buf; /* buffer for literals or lengths */
+
+ uInt lit_bufsize;
+ /* Size of match buffer for literals/lengths. There are 4 reasons for
+ * limiting lit_bufsize to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input
+ * data is still in the window so we can still emit a stored block even
+ * when input comes from standard input. (This can also be done for
+ * all blocks if lit_bufsize is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * This is applicable only for zip (not gzip or zlib).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting
+ * trees more frequently.
+ * - I can't count above 4
+ */
+
+ uInt last_lit; /* running index in l_buf */
+
+ ushf *d_buf;
+ /* Buffer for distances. To simplify the code, d_buf and l_buf have
+ * the same number of elements. To use different lengths, an extra flag
+ * array would be necessary.
+ */
+
+ ulg opt_len; /* bit length of current block with optimal trees */
+ ulg static_len; /* bit length of current block with static trees */
+ uInt matches; /* number of string matches in current block */
+ int last_eob_len; /* bit length of EOB code for last block */
+
+#ifdef DEBUG
+ ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
+#endif
+
+ ush bi_buf;
+ /* Output buffer. bits are inserted starting at the bottom (least
+ * significant bits).
+ */
+ int bi_valid;
+ /* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+ /* in trees.c */
+void _tr_init OF((deflate_state *s));
+int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
+void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+void _tr_align OF((deflate_state *s));
+void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+
+#define d_code(dist) \
+ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+ extern uch _length_code[];
+ extern uch _dist_code[];
+#else
+ extern const uch _length_code[];
+ extern const uch _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+ { uch cc = (c); \
+ s->d_buf[s->last_lit] = 0; \
+ s->l_buf[s->last_lit++] = cc; \
+ s->dyn_ltree[cc].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+# define _tr_tally_dist(s, distance, length, flush) \
+ { uch len = (length); \
+ ush dist = (distance); \
+ s->d_buf[s->last_lit] = dist; \
+ s->l_buf[s->last_lit++] = len; \
+ dist--; \
+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+ s->dyn_dtree[d_code(dist)].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+ flush = _tr_tally(s, distance, length)
+#endif
+
+#endif
diff --git a/cfe/cfe/zlib/descrip.mms b/cfe/cfe/zlib/descrip.mms
new file mode 100644
index 0000000..9d36459
--- /dev/null
+++ b/cfe/cfe/zlib/descrip.mms
@@ -0,0 +1,48 @@
+# descrip.mms: MMS description file for building zlib on VMS
+# written by Martin P.J. Zinser <m.zinser@gsi.de>
+
+cc_defs =
+c_deb =
+
+.ifdef __DECC__
+pref = /prefix=all
+.endif
+
+OBJS = adler32.obj, compress.obj, crc32.obj, gzio.obj, uncompr.obj,\
+ deflate.obj, trees.obj, zutil.obj, inflate.obj, infblock.obj,\
+ inftrees.obj, infcodes.obj, infutil.obj, inffast.obj
+
+CFLAGS= $(C_DEB) $(CC_DEFS) $(PREF)
+
+all : example.exe minigzip.exe
+ @ write sys$output " Example applications available"
+libz.olb : libz.olb($(OBJS))
+ @ write sys$output " libz available"
+
+example.exe : example.obj libz.olb
+ link example,libz.olb/lib
+
+minigzip.exe : minigzip.obj libz.olb
+ link minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib
+
+clean :
+ delete *.obj;*,libz.olb;*
+
+
+# Other dependencies.
+adler32.obj : zutil.h zlib.h zconf.h
+compress.obj : zlib.h zconf.h
+crc32.obj : zutil.h zlib.h zconf.h
+deflate.obj : deflate.h zutil.h zlib.h zconf.h
+example.obj : zlib.h zconf.h
+gzio.obj : zutil.h zlib.h zconf.h
+infblock.obj : zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h
+infcodes.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h inffast.h
+inffast.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h
+inflate.obj : zutil.h zlib.h zconf.h infblock.h
+inftrees.obj : zutil.h zlib.h zconf.h inftrees.h
+infutil.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h
+minigzip.obj : zlib.h zconf.h
+trees.obj : deflate.h zutil.h zlib.h zconf.h
+uncompr.obj : zlib.h zconf.h
+zutil.obj : zutil.h zlib.h zconf.h
diff --git a/cfe/cfe/zlib/example.c b/cfe/cfe/zlib/example.c
new file mode 100644
index 0000000..63a1b1e
--- /dev/null
+++ b/cfe/cfe/zlib/example.c
@@ -0,0 +1,556 @@
+/* example.c -- usage example of the zlib compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: example.c,v 1.1 2001/11/09 01:48:02 mpl Exp $ */
+
+#include <stdio.h>
+#include "zlib.h"
+
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+#else
+ extern void exit OF((int));
+#endif
+
+#if defined(VMS) || defined(RISCOS)
+# define TESTFILE "foo-gz"
+#else
+# define TESTFILE "foo.gz"
+#endif
+
+#define CHECK_ERR(err, msg) { \
+ if (err != Z_OK) { \
+ fprintf(stderr, "%s error: %d\n", msg, err); \
+ exit(1); \
+ } \
+}
+
+const char hello[] = "hello, hello!";
+/* "hello world" would be more standard, but the repeated "hello"
+ * stresses the compression code better, sorry...
+ */
+
+const char dictionary[] = "hello";
+uLong dictId; /* Adler32 value of the dictionary */
+
+void test_compress OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_gzio OF((const char *out, const char *in,
+ Byte *uncompr, int uncomprLen));
+void test_deflate OF((Byte *compr, uLong comprLen));
+void test_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_large_deflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_large_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_flush OF((Byte *compr, uLong *comprLen));
+void test_sync OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_dict_deflate OF((Byte *compr, uLong comprLen));
+void test_dict_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+int main OF((int argc, char *argv[]));
+
+/* ===========================================================================
+ * Test compress() and uncompress()
+ */
+void test_compress(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ uLong len = strlen(hello)+1;
+
+ err = compress(compr, &comprLen, (const Bytef*)hello, len);
+ CHECK_ERR(err, "compress");
+
+ strcpy((char*)uncompr, "garbage");
+
+ err = uncompress(uncompr, &uncomprLen, compr, comprLen);
+ CHECK_ERR(err, "uncompress");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad uncompress\n");
+ exit(1);
+ } else {
+ printf("uncompress(): %s\n", (char *)uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Test read/write of .gz files
+ */
+void test_gzio(out, in, uncompr, uncomprLen)
+ const char *out; /* compressed output file */
+ const char *in; /* compressed input file */
+ Byte *uncompr;
+ int uncomprLen;
+{
+ int err;
+ int len = strlen(hello)+1;
+ gzFile file;
+ z_off_t pos;
+
+ file = gzopen(out, "wb");
+ if (file == NULL) {
+ fprintf(stderr, "gzopen error\n");
+ exit(1);
+ }
+ gzputc(file, 'h');
+ if (gzputs(file, "ello") != 4) {
+ fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
+ exit(1);
+ }
+ if (gzprintf(file, ", %s!", "hello") != 8) {
+ fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
+ exit(1);
+ }
+ gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
+ gzclose(file);
+
+ file = gzopen(in, "rb");
+ if (file == NULL) {
+ fprintf(stderr, "gzopen error\n");
+ }
+ strcpy((char*)uncompr, "garbage");
+
+ uncomprLen = gzread(file, uncompr, (unsigned)uncomprLen);
+ if (uncomprLen != len) {
+ fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
+ exit(1);
+ }
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
+ exit(1);
+ } else {
+ printf("gzread(): %s\n", (char *)uncompr);
+ }
+
+ pos = gzseek(file, -8L, SEEK_CUR);
+ if (pos != 6 || gztell(file) != pos) {
+ fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
+ (long)pos, (long)gztell(file));
+ exit(1);
+ }
+
+ if (gzgetc(file) != ' ') {
+ fprintf(stderr, "gzgetc error\n");
+ exit(1);
+ }
+
+ gzgets(file, (char*)uncompr, uncomprLen);
+ uncomprLen = strlen((char*)uncompr);
+ if (uncomprLen != 6) { /* "hello!" */
+ fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
+ exit(1);
+ }
+ if (strcmp((char*)uncompr, hello+7)) {
+ fprintf(stderr, "bad gzgets after gzseek\n");
+ exit(1);
+ } else {
+ printf("gzgets() after gzseek: %s\n", (char *)uncompr);
+ }
+
+ gzclose(file);
+}
+
+/* ===========================================================================
+ * Test deflate() with small buffers
+ */
+void test_deflate(compr, comprLen)
+ Byte *compr;
+ uLong comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+ int len = strlen(hello)+1;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.next_out = compr;
+
+ while (c_stream.total_in != (uLong)len && c_stream.total_out < comprLen) {
+ c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+ }
+ /* Finish the stream, still forcing small buffers: */
+ for (;;) {
+ c_stream.avail_out = 1;
+ err = deflate(&c_stream, Z_FINISH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "deflate");
+ }
+
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with small buffers
+ */
+void test_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = 0;
+ d_stream.next_out = uncompr;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
+ d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "inflate");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad inflate\n");
+ exit(1);
+ } else {
+ printf("inflate(): %s\n", (char *)uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Test deflate() with large buffers and dynamic change of compression level
+ */
+void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_BEST_SPEED);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_out = compr;
+ c_stream.avail_out = (uInt)comprLen;
+
+ /* At this point, uncompr is still mostly zeroes, so it should compress
+ * very well:
+ */
+ c_stream.next_in = uncompr;
+ c_stream.avail_in = (uInt)uncomprLen;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+ if (c_stream.avail_in != 0) {
+ fprintf(stderr, "deflate not greedy\n");
+ exit(1);
+ }
+
+ /* Feed in already compressed data and switch to no compression: */
+ deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
+ c_stream.next_in = compr;
+ c_stream.avail_in = (uInt)comprLen/2;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ /* Switch back to compressing mode: */
+ deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
+ c_stream.next_in = uncompr;
+ c_stream.avail_in = (uInt)uncomprLen;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ fprintf(stderr, "deflate should report Z_STREAM_END\n");
+ exit(1);
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with large buffers
+ */
+void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = (uInt)comprLen;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ for (;;) {
+ d_stream.next_out = uncompr; /* discard the output */
+ d_stream.avail_out = (uInt)uncomprLen;
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "large inflate");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
+ fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
+ exit(1);
+ } else {
+ printf("large_inflate(): OK\n");
+ }
+}
+
+/* ===========================================================================
+ * Test deflate() with full flush
+ */
+void test_flush(compr, comprLen)
+ Byte *compr;
+ uLong *comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+ int len = strlen(hello)+1;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.next_out = compr;
+ c_stream.avail_in = 3;
+ c_stream.avail_out = (uInt)*comprLen;
+ err = deflate(&c_stream, Z_FULL_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ compr[3]++; /* force an error in first compressed block */
+ c_stream.avail_in = len - 3;
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ CHECK_ERR(err, "deflate");
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+
+ *comprLen = c_stream.total_out;
+}
+
+/* ===========================================================================
+ * Test inflateSync()
+ */
+void test_sync(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = 2; /* just read the zlib header */
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ d_stream.next_out = uncompr;
+ d_stream.avail_out = (uInt)uncomprLen;
+
+ inflate(&d_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "inflate");
+
+ d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */
+ err = inflateSync(&d_stream); /* but skip the damaged part */
+ CHECK_ERR(err, "inflateSync");
+
+ err = inflate(&d_stream, Z_FINISH);
+ if (err != Z_DATA_ERROR) {
+ fprintf(stderr, "inflate should report DATA_ERROR\n");
+ /* Because of incorrect adler32 */
+ exit(1);
+ }
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ printf("after inflateSync(): hel%s\n", (char *)uncompr);
+}
+
+/* ===========================================================================
+ * Test deflate() with preset dictionary
+ */
+void test_dict_deflate(compr, comprLen)
+ Byte *compr;
+ uLong comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ err = deflateSetDictionary(&c_stream,
+ (const Bytef*)dictionary, sizeof(dictionary));
+ CHECK_ERR(err, "deflateSetDictionary");
+
+ dictId = c_stream.adler;
+ c_stream.next_out = compr;
+ c_stream.avail_out = (uInt)comprLen;
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.avail_in = (uInt)strlen(hello)+1;
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ fprintf(stderr, "deflate should report Z_STREAM_END\n");
+ exit(1);
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with a preset dictionary
+ */
+void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = (uInt)comprLen;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ d_stream.next_out = uncompr;
+ d_stream.avail_out = (uInt)uncomprLen;
+
+ for (;;) {
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ if (err == Z_NEED_DICT) {
+ if (d_stream.adler != dictId) {
+ fprintf(stderr, "unexpected dictionary");
+ exit(1);
+ }
+ err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
+ sizeof(dictionary));
+ }
+ CHECK_ERR(err, "inflate with dict");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad inflate with dict\n");
+ exit(1);
+ } else {
+ printf("inflate with dictionary: %s\n", (char *)uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Usage: example [output.gz [input.gz]]
+ */
+
+int main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ Byte *compr, *uncompr;
+ uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
+ uLong uncomprLen = comprLen;
+ static const char* myVersion = ZLIB_VERSION;
+
+ if (zlibVersion()[0] != myVersion[0]) {
+ fprintf(stderr, "incompatible zlib version\n");
+ exit(1);
+
+ } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
+ fprintf(stderr, "warning: different zlib version\n");
+ }
+
+ compr = (Byte*)calloc((uInt)comprLen, 1);
+ uncompr = (Byte*)calloc((uInt)uncomprLen, 1);
+ /* compr and uncompr are cleared to avoid reading uninitialized
+ * data and to ensure that uncompr compresses well.
+ */
+ if (compr == Z_NULL || uncompr == Z_NULL) {
+ printf("out of memory\n");
+ exit(1);
+ }
+ test_compress(compr, comprLen, uncompr, uncomprLen);
+
+ test_gzio((argc > 1 ? argv[1] : TESTFILE),
+ (argc > 2 ? argv[2] : TESTFILE),
+ uncompr, (int)uncomprLen);
+
+ test_deflate(compr, comprLen);
+ test_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ test_large_deflate(compr, comprLen, uncompr, uncomprLen);
+ test_large_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ test_flush(compr, &comprLen);
+ test_sync(compr, comprLen, uncompr, uncomprLen);
+ comprLen = uncomprLen;
+
+ test_dict_deflate(compr, comprLen);
+ test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ exit(0);
+ return 0; /* to avoid warning */
+}
diff --git a/cfe/cfe/zlib/gzio.c b/cfe/cfe/zlib/gzio.c
new file mode 100644
index 0000000..6dfd489
--- /dev/null
+++ b/cfe/cfe/zlib/gzio.c
@@ -0,0 +1,875 @@
+/* gzio.c -- IO on .gz files
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Compile this file with -DNO_DEFLATE to avoid the compression code.
+ */
+
+/* @(#) $Id: gzio.c,v 1.1 2001/11/09 01:48:02 mpl Exp $ */
+
+#include <stdio.h>
+
+#include "zutil.h"
+
+struct internal_state {int dummy;}; /* for buggy compilers */
+
+#ifndef Z_BUFSIZE
+# ifdef MAXSEG_64K
+# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
+# else
+# define Z_BUFSIZE 16384
+# endif
+#endif
+#ifndef Z_PRINTF_BUFSIZE
+# define Z_PRINTF_BUFSIZE 4096
+#endif
+
+#define ALLOC(size) malloc(size)
+#define TRYFREE(p) {if (p) free(p);}
+
+static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
+
+/* gzip flag byte */
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define RESERVED 0xE0 /* bits 5..7: reserved */
+
+typedef struct gz_stream {
+ z_stream stream;
+ int z_err; /* error code for last stream operation */
+ int z_eof; /* set if end of input file */
+ FILE *file; /* .gz file */
+ Byte *inbuf; /* input buffer */
+ Byte *outbuf; /* output buffer */
+ uLong crc; /* crc32 of uncompressed data */
+ char *msg; /* error message */
+ char *path; /* path name for debugging only */
+ int transparent; /* 1 if input file is not a .gz file */
+ char mode; /* 'w' or 'r' */
+ long startpos; /* start of compressed data in file (header skipped) */
+} gz_stream;
+
+
+local gzFile gz_open OF((const char *path, const char *mode, int fd));
+local int do_flush OF((gzFile file, int flush));
+local int get_byte OF((gz_stream *s));
+local void check_header OF((gz_stream *s));
+local int destroy OF((gz_stream *s));
+local void putLong OF((FILE *file, uLong x));
+local uLong getLong OF((gz_stream *s));
+
+/* ===========================================================================
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb"). The file is given either by file descriptor
+ or path name (if fd == -1).
+ gz_open return NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR).
+*/
+local gzFile gz_open (path, mode, fd)
+ const char *path;
+ const char *mode;
+ int fd;
+{
+ int err;
+ int level = Z_DEFAULT_COMPRESSION; /* compression level */
+ int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
+ char *p = (char*)mode;
+ gz_stream *s;
+ char fmode[80]; /* copy of mode, without the compression level */
+ char *m = fmode;
+
+ if (!path || !mode) return Z_NULL;
+
+ s = (gz_stream *)ALLOC(sizeof(gz_stream));
+ if (!s) return Z_NULL;
+
+ s->stream.zalloc = (alloc_func)0;
+ s->stream.zfree = (free_func)0;
+ s->stream.opaque = (voidpf)0;
+ s->stream.next_in = s->inbuf = Z_NULL;
+ s->stream.next_out = s->outbuf = Z_NULL;
+ s->stream.avail_in = s->stream.avail_out = 0;
+ s->file = NULL;
+ s->z_err = Z_OK;
+ s->z_eof = 0;
+ s->crc = crc32(0L, Z_NULL, 0);
+ s->msg = NULL;
+ s->transparent = 0;
+
+ s->path = (char*)ALLOC(strlen(path)+1);
+ if (s->path == NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ strcpy(s->path, path); /* do this early for debugging */
+
+ s->mode = '\0';
+ do {
+ if (*p == 'r') s->mode = 'r';
+ if (*p == 'w' || *p == 'a') s->mode = 'w';
+ if (*p >= '0' && *p <= '9') {
+ level = *p - '0';
+ } else if (*p == 'f') {
+ strategy = Z_FILTERED;
+ } else if (*p == 'h') {
+ strategy = Z_HUFFMAN_ONLY;
+ } else {
+ *m++ = *p; /* copy the mode */
+ }
+ } while (*p++ && m != fmode + sizeof(fmode));
+ if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
+
+ if (s->mode == 'w') {
+#ifdef NO_DEFLATE
+ err = Z_STREAM_ERROR;
+#else
+ err = deflateInit2(&(s->stream), level,
+ Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
+ /* windowBits is passed < 0 to suppress zlib header */
+
+ s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
+#endif
+ if (err != Z_OK || s->outbuf == Z_NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ } else {
+ s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
+
+ err = inflateInit2(&(s->stream), -MAX_WBITS);
+ /* windowBits is passed < 0 to tell that there is no zlib header.
+ * Note that in this case inflate *requires* an extra "dummy" byte
+ * after the compressed stream in order to complete decompression and
+ * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
+ * present after the compressed stream.
+ */
+ if (err != Z_OK || s->inbuf == Z_NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ }
+ s->stream.avail_out = Z_BUFSIZE;
+
+ errno = 0;
+ s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
+
+ if (s->file == NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ if (s->mode == 'w') {
+ /* Write a very simple .gz header:
+ */
+ fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
+ Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
+ s->startpos = 10L;
+ /* We use 10L instead of ftell(s->file) to because ftell causes an
+ * fflush on some systems. This version of the library doesn't use
+ * startpos anyway in write mode, so this initialization is not
+ * necessary.
+ */
+ } else {
+ check_header(s); /* skip the .gz header */
+ s->startpos = (ftell(s->file) - s->stream.avail_in);
+ }
+
+ return (gzFile)s;
+}
+
+/* ===========================================================================
+ Opens a gzip (.gz) file for reading or writing.
+*/
+gzFile ZEXPORT gzopen (path, mode)
+ const char *path;
+ const char *mode;
+{
+ return gz_open (path, mode, -1);
+}
+
+/* ===========================================================================
+ Associate a gzFile with the file descriptor fd. fd is not dup'ed here
+ to mimic the behavio(u)r of fdopen.
+*/
+gzFile ZEXPORT gzdopen (fd, mode)
+ int fd;
+ const char *mode;
+{
+ char name[20];
+
+ if (fd < 0) return (gzFile)Z_NULL;
+ sprintf(name, "<fd:%d>", fd); /* for debugging */
+
+ return gz_open (name, mode, fd);
+}
+
+/* ===========================================================================
+ * Update the compression level and strategy
+ */
+int ZEXPORT gzsetparams (file, level, strategy)
+ gzFile file;
+ int level;
+ int strategy;
+{
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+ /* Make room to allow flushing */
+ if (s->stream.avail_out == 0) {
+
+ s->stream.next_out = s->outbuf;
+ if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
+ s->z_err = Z_ERRNO;
+ }
+ s->stream.avail_out = Z_BUFSIZE;
+ }
+
+ return deflateParams (&(s->stream), level, strategy);
+}
+
+/* ===========================================================================
+ Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+ for end of file.
+ IN assertion: the stream s has been sucessfully opened for reading.
+*/
+local int get_byte(s)
+ gz_stream *s;
+{
+ if (s->z_eof) return EOF;
+ if (s->stream.avail_in == 0) {
+ errno = 0;
+ s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+ if (s->stream.avail_in == 0) {
+ s->z_eof = 1;
+ if (ferror(s->file)) s->z_err = Z_ERRNO;
+ return EOF;
+ }
+ s->stream.next_in = s->inbuf;
+ }
+ s->stream.avail_in--;
+ return *(s->stream.next_in)++;
+}
+
+/* ===========================================================================
+ Check the gzip header of a gz_stream opened for reading. Set the stream
+ mode to transparent if the gzip magic header is not present; set s->err
+ to Z_DATA_ERROR if the magic header is present but the rest of the header
+ is incorrect.
+ IN assertion: the stream s has already been created sucessfully;
+ s->stream.avail_in is zero for the first time, but may be non-zero
+ for concatenated .gz files.
+*/
+local void check_header(s)
+ gz_stream *s;
+{
+ int method; /* method byte */
+ int flags; /* flags byte */
+ uInt len;
+ int c;
+
+ /* Check the gzip magic header */
+ for (len = 0; len < 2; len++) {
+ c = get_byte(s);
+ if (c != gz_magic[len]) {
+ if (len != 0) s->stream.avail_in++, s->stream.next_in--;
+ if (c != EOF) {
+ s->stream.avail_in++, s->stream.next_in--;
+ s->transparent = 1;
+ }
+ s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
+ return;
+ }
+ }
+ method = get_byte(s);
+ flags = get_byte(s);
+ if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
+ s->z_err = Z_DATA_ERROR;
+ return;
+ }
+
+ /* Discard time, xflags and OS code: */
+ for (len = 0; len < 6; len++) (void)get_byte(s);
+
+ if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
+ len = (uInt)get_byte(s);
+ len += ((uInt)get_byte(s))<<8;
+ /* len is garbage if EOF but the loop below will quit anyway */
+ while (len-- != 0 && get_byte(s) != EOF) ;
+ }
+ if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
+ while ((c = get_byte(s)) != 0 && c != EOF) ;
+ }
+ if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
+ while ((c = get_byte(s)) != 0 && c != EOF) ;
+ }
+ if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
+ for (len = 0; len < 2; len++) (void)get_byte(s);
+ }
+ s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
+}
+
+ /* ===========================================================================
+ * Cleanup then free the given gz_stream. Return a zlib error code.
+ Try freeing in the reverse order of allocations.
+ */
+local int destroy (s)
+ gz_stream *s;
+{
+ int err = Z_OK;
+
+ if (!s) return Z_STREAM_ERROR;
+
+ TRYFREE(s->msg);
+
+ if (s->stream.state != NULL) {
+ if (s->mode == 'w') {
+#ifdef NO_DEFLATE
+ err = Z_STREAM_ERROR;
+#else
+ err = deflateEnd(&(s->stream));
+#endif
+ } else if (s->mode == 'r') {
+ err = inflateEnd(&(s->stream));
+ }
+ }
+ if (s->file != NULL && fclose(s->file)) {
+#ifdef ESPIPE
+ if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
+#endif
+ err = Z_ERRNO;
+ }
+ if (s->z_err < 0) err = s->z_err;
+
+ TRYFREE(s->inbuf);
+ TRYFREE(s->outbuf);
+ TRYFREE(s->path);
+ TRYFREE(s);
+ return err;
+}
+
+/* ===========================================================================
+ Reads the given number of uncompressed bytes from the compressed file.
+ gzread returns the number of bytes actually read (0 for end of file).
+*/
+int ZEXPORT gzread (file, buf, len)
+ gzFile file;
+ voidp buf;
+ unsigned len;
+{
+ gz_stream *s = (gz_stream*)file;
+ Bytef *start = (Bytef*)buf; /* starting point for crc computation */
+ Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */
+
+ if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
+
+ if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
+ if (s->z_err == Z_STREAM_END) return 0; /* EOF */
+
+ next_out = (Byte*)buf;
+ s->stream.next_out = (Bytef*)buf;
+ s->stream.avail_out = len;
+
+ while (s->stream.avail_out != 0) {
+
+ if (s->transparent) {
+ /* Copy first the lookahead bytes: */
+ uInt n = s->stream.avail_in;
+ if (n > s->stream.avail_out) n = s->stream.avail_out;
+ if (n > 0) {
+ zmemcpy(s->stream.next_out, s->stream.next_in, n);
+ next_out += n;
+ s->stream.next_out = next_out;
+ s->stream.next_in += n;
+ s->stream.avail_out -= n;
+ s->stream.avail_in -= n;
+ }
+ if (s->stream.avail_out > 0) {
+ s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
+ s->file);
+ }
+ len -= s->stream.avail_out;
+ s->stream.total_in += (uLong)len;
+ s->stream.total_out += (uLong)len;
+ if (len == 0) s->z_eof = 1;
+ return (int)len;
+ }
+ if (s->stream.avail_in == 0 && !s->z_eof) {
+
+ errno = 0;
+ s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+ if (s->stream.avail_in == 0) {
+ s->z_eof = 1;
+ if (ferror(s->file)) {
+ s->z_err = Z_ERRNO;
+ break;
+ }
+ }
+ s->stream.next_in = s->inbuf;
+ }
+ s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
+
+ if (s->z_err == Z_STREAM_END) {
+ /* Check CRC and original size */
+ s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+ start = s->stream.next_out;
+
+ if (getLong(s) != s->crc) {
+ s->z_err = Z_DATA_ERROR;
+ } else {
+ (void)getLong(s);
+ /* The uncompressed length returned by above getlong() may
+ * be different from s->stream.total_out) in case of
+ * concatenated .gz files. Check for such files:
+ */
+ check_header(s);
+ if (s->z_err == Z_OK) {
+ uLong total_in = s->stream.total_in;
+ uLong total_out = s->stream.total_out;
+
+ inflateReset(&(s->stream));
+ s->stream.total_in = total_in;
+ s->stream.total_out = total_out;
+ s->crc = crc32(0L, Z_NULL, 0);
+ }
+ }
+ }
+ if (s->z_err != Z_OK || s->z_eof) break;
+ }
+ s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+
+ return (int)(len - s->stream.avail_out);
+}
+
+
+/* ===========================================================================
+ Reads one byte from the compressed file. gzgetc returns this byte
+ or -1 in case of end of file or error.
+*/
+int ZEXPORT gzgetc(file)
+ gzFile file;
+{
+ unsigned char c;
+
+ return gzread(file, &c, 1) == 1 ? c : -1;
+}
+
+
+/* ===========================================================================
+ Reads bytes from the compressed file until len-1 characters are
+ read, or a newline character is read and transferred to buf, or an
+ end-of-file condition is encountered. The string is then terminated
+ with a null character.
+ gzgets returns buf, or Z_NULL in case of error.
+
+ The current implementation is not optimized at all.
+*/
+char * ZEXPORT gzgets(file, buf, len)
+ gzFile file;
+ char *buf;
+ int len;
+{
+ char *b = buf;
+ if (buf == Z_NULL || len <= 0) return Z_NULL;
+
+ while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
+ *buf = '\0';
+ return b == buf && len > 0 ? Z_NULL : b;
+}
+
+
+#ifndef NO_DEFLATE
+/* ===========================================================================
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of bytes actually written (0 in case of error).
+*/
+int ZEXPORT gzwrite (file, buf, len)
+ gzFile file;
+ const voidp buf;
+ unsigned len;
+{
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+ s->stream.next_in = (Bytef*)buf;
+ s->stream.avail_in = len;
+
+ while (s->stream.avail_in != 0) {
+
+ if (s->stream.avail_out == 0) {
+
+ s->stream.next_out = s->outbuf;
+ if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
+ s->z_err = Z_ERRNO;
+ break;
+ }
+ s->stream.avail_out = Z_BUFSIZE;
+ }
+ s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
+ if (s->z_err != Z_OK) break;
+ }
+ s->crc = crc32(s->crc, (const Bytef *)buf, len);
+
+ return (int)(len - s->stream.avail_in);
+}
+
+/* ===========================================================================
+ Converts, formats, and writes the args to the compressed file under
+ control of the format string, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written (0 in case of error).
+*/
+#ifdef STDC
+#include <stdarg.h>
+
+int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
+{
+ char buf[Z_PRINTF_BUFSIZE];
+ va_list va;
+ int len;
+
+ va_start(va, format);
+#ifdef HAS_vsnprintf
+ (void)vsnprintf(buf, sizeof(buf), format, va);
+#else
+ (void)vsprintf(buf, format, va);
+#endif
+ va_end(va);
+ len = strlen(buf); /* some *sprintf don't return the nb of bytes written */
+ if (len <= 0) return 0;
+
+ return gzwrite(file, buf, (unsigned)len);
+}
+#else /* not ANSI C */
+
+int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
+ a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
+ gzFile file;
+ const char *format;
+ int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
+ a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
+{
+ char buf[Z_PRINTF_BUFSIZE];
+ int len;
+
+#ifdef HAS_snprintf
+ snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
+ a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+#else
+ sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
+ a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+#endif
+ len = strlen(buf); /* old sprintf doesn't return the nb of bytes written */
+ if (len <= 0) return 0;
+
+ return gzwrite(file, buf, len);
+}
+#endif
+
+/* ===========================================================================
+ Writes c, converted to an unsigned char, into the compressed file.
+ gzputc returns the value that was written, or -1 in case of error.
+*/
+int ZEXPORT gzputc(file, c)
+ gzFile file;
+ int c;
+{
+ unsigned char cc = (unsigned char) c; /* required for big endian systems */
+
+ return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
+}
+
+
+/* ===========================================================================
+ Writes the given null-terminated string to the compressed file, excluding
+ the terminating null character.
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+int ZEXPORT gzputs(file, s)
+ gzFile file;
+ const char *s;
+{
+ return gzwrite(file, (char*)s, (unsigned)strlen(s));
+}
+
+
+/* ===========================================================================
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function.
+*/
+local int do_flush (file, flush)
+ gzFile file;
+ int flush;
+{
+ uInt len;
+ int done = 0;
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+ s->stream.avail_in = 0; /* should be zero already anyway */
+
+ for (;;) {
+ len = Z_BUFSIZE - s->stream.avail_out;
+
+ if (len != 0) {
+ if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
+ s->z_err = Z_ERRNO;
+ return Z_ERRNO;
+ }
+ s->stream.next_out = s->outbuf;
+ s->stream.avail_out = Z_BUFSIZE;
+ }
+ if (done) break;
+ s->z_err = deflate(&(s->stream), flush);
+
+ /* Ignore the second of two consecutive flushes: */
+ if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
+
+ /* deflate has finished flushing only when it hasn't used up
+ * all the available space in the output buffer:
+ */
+ done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
+
+ if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
+ }
+ return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
+}
+
+int ZEXPORT gzflush (file, flush)
+ gzFile file;
+ int flush;
+{
+ gz_stream *s = (gz_stream*)file;
+ int err = do_flush (file, flush);
+
+ if (err) return err;
+ fflush(s->file);
+ return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
+}
+#endif /* NO_DEFLATE */
+
+/* ===========================================================================
+ Sets the starting position for the next gzread or gzwrite on the given
+ compressed file. The offset represents a number of bytes in the
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error.
+ SEEK_END is not implemented, returns error.
+ In this version of the library, gzseek can be extremely slow.
+*/
+z_off_t ZEXPORT gzseek (file, offset, whence)
+ gzFile file;
+ z_off_t offset;
+ int whence;
+{
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL || whence == SEEK_END ||
+ s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
+ return -1L;
+ }
+
+ if (s->mode == 'w') {
+#ifdef NO_DEFLATE
+ return -1L;
+#else
+ if (whence == SEEK_SET) {
+ offset -= s->stream.total_in;
+ }
+ if (offset < 0) return -1L;
+
+ /* At this point, offset is the number of zero bytes to write. */
+ if (s->inbuf == Z_NULL) {
+ s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
+ zmemzero(s->inbuf, Z_BUFSIZE);
+ }
+ while (offset > 0) {
+ uInt size = Z_BUFSIZE;
+ if (offset < Z_BUFSIZE) size = (uInt)offset;
+
+ size = gzwrite(file, s->inbuf, size);
+ if (size == 0) return -1L;
+
+ offset -= size;
+ }
+ return (z_off_t)s->stream.total_in;
+#endif
+ }
+ /* Rest of function is for reading only */
+
+ /* compute absolute position */
+ if (whence == SEEK_CUR) {
+ offset += s->stream.total_out;
+ }
+ if (offset < 0) return -1L;
+
+ if (s->transparent) {
+ /* map to fseek */
+ s->stream.avail_in = 0;
+ s->stream.next_in = s->inbuf;
+ if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
+
+ s->stream.total_in = s->stream.total_out = (uLong)offset;
+ return offset;
+ }
+
+ /* For a negative seek, rewind and use positive seek */
+ if ((uLong)offset >= s->stream.total_out) {
+ offset -= s->stream.total_out;
+ } else if (gzrewind(file) < 0) {
+ return -1L;
+ }
+ /* offset is now the number of bytes to skip. */
+
+ if (offset != 0 && s->outbuf == Z_NULL) {
+ s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
+ }
+ while (offset > 0) {
+ int size = Z_BUFSIZE;
+ if (offset < Z_BUFSIZE) size = (int)offset;
+
+ size = gzread(file, s->outbuf, (uInt)size);
+ if (size <= 0) return -1L;
+ offset -= size;
+ }
+ return (z_off_t)s->stream.total_out;
+}
+
+/* ===========================================================================
+ Rewinds input file.
+*/
+int ZEXPORT gzrewind (file)
+ gzFile file;
+{
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL || s->mode != 'r') return -1;
+
+ s->z_err = Z_OK;
+ s->z_eof = 0;
+ s->stream.avail_in = 0;
+ s->stream.next_in = s->inbuf;
+ s->crc = crc32(0L, Z_NULL, 0);
+
+ if (s->startpos == 0) { /* not a compressed file */
+ rewind(s->file);
+ return 0;
+ }
+
+ (void) inflateReset(&s->stream);
+ return fseek(s->file, s->startpos, SEEK_SET);
+}
+
+/* ===========================================================================
+ Returns the starting position for the next gzread or gzwrite on the
+ given compressed file. This position represents a number of bytes in the
+ uncompressed data stream.
+*/
+z_off_t ZEXPORT gztell (file)
+ gzFile file;
+{
+ return gzseek(file, 0L, SEEK_CUR);
+}
+
+/* ===========================================================================
+ Returns 1 when EOF has previously been detected reading the given
+ input stream, otherwise zero.
+*/
+int ZEXPORT gzeof (file)
+ gzFile file;
+{
+ gz_stream *s = (gz_stream*)file;
+
+ return (s == NULL || s->mode != 'r') ? 0 : s->z_eof;
+}
+
+/* ===========================================================================
+ Outputs a long in LSB order to the given file
+*/
+local void putLong (file, x)
+ FILE *file;
+ uLong x;
+{
+ int n;
+ for (n = 0; n < 4; n++) {
+ fputc((int)(x & 0xff), file);
+ x >>= 8;
+ }
+}
+
+/* ===========================================================================
+ Reads a long in LSB order from the given gz_stream. Sets z_err in case
+ of error.
+*/
+local uLong getLong (s)
+ gz_stream *s;
+{
+ uLong x = (uLong)get_byte(s);
+ int c;
+
+ x += ((uLong)get_byte(s))<<8;
+ x += ((uLong)get_byte(s))<<16;
+ c = get_byte(s);
+ if (c == EOF) s->z_err = Z_DATA_ERROR;
+ x += ((uLong)c)<<24;
+ return x;
+}
+
+/* ===========================================================================
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state.
+*/
+int ZEXPORT gzclose (file)
+ gzFile file;
+{
+ int err;
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL) return Z_STREAM_ERROR;
+
+ if (s->mode == 'w') {
+#ifdef NO_DEFLATE
+ return Z_STREAM_ERROR;
+#else
+ err = do_flush (file, Z_FINISH);
+ if (err != Z_OK) return destroy((gz_stream*)file);
+
+ putLong (s->file, s->crc);
+ putLong (s->file, s->stream.total_in);
+#endif
+ }
+ return destroy((gz_stream*)file);
+}
+
+/* ===========================================================================
+ Returns the error message for the last error which occured on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occured in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+const char* ZEXPORT gzerror (file, errnum)
+ gzFile file;
+ int *errnum;
+{
+ char *m;
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL) {
+ *errnum = Z_STREAM_ERROR;
+ return (const char*)ERR_MSG(Z_STREAM_ERROR);
+ }
+ *errnum = s->z_err;
+ if (*errnum == Z_OK) return (const char*)"";
+
+ m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
+
+ if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
+
+ TRYFREE(s->msg);
+ s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
+ strcpy(s->msg, s->path);
+ strcat(s->msg, ": ");
+ strcat(s->msg, m);
+ return (const char*)s->msg;
+}
diff --git a/cfe/cfe/zlib/infblock.c b/cfe/cfe/zlib/infblock.c
new file mode 100644
index 0000000..f4920fa
--- /dev/null
+++ b/cfe/cfe/zlib/infblock.c
@@ -0,0 +1,398 @@
+/* infblock.c -- interpret and process block types to last block
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* Table for deflate from PKZIP's appnote.txt. */
+local const uInt border[] = { /* Order of the bit length code lengths */
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+/*
+ Notes beyond the 1.93a appnote.txt:
+
+ 1. Distance pointers never point before the beginning of the output
+ stream.
+ 2. Distance pointers can point back across blocks, up to 32k away.
+ 3. There is an implied maximum of 7 bits for the bit length table and
+ 15 bits for the actual data.
+ 4. If only one code exists, then it is encoded using one bit. (Zero
+ would be more efficient, but perhaps a little confusing.) If two
+ codes exist, they are coded using one bit each (0 and 1).
+ 5. There is no way of sending zero distance codes--a dummy must be
+ sent if there are none. (History: a pre 2.0 version of PKZIP would
+ store blocks with no distance codes, but this was discovered to be
+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
+ zero distance codes, which is sent as one code of zero bits in
+ length.
+ 6. There are up to 286 literal/length codes. Code 256 represents the
+ end-of-block. Note however that the static length tree defines
+ 288 codes just to fill out the Huffman codes. Codes 286 and 287
+ cannot be used though, since there is no length base or extra bits
+ defined for them. Similarily, there are up to 30 distance codes.
+ However, static trees define 32 codes (all 5 bits) to fill out the
+ Huffman codes, but the last two had better not show up in the data.
+ 7. Unzip can check dynamic Huffman blocks for complete code sets.
+ The exception is that a single code would not be complete (see #4).
+ 8. The five bits following the block type is really the number of
+ literal codes sent minus 257.
+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+ (1+6+6). Therefore, to output three times the length, you output
+ three codes (1+1+1), whereas to output four times the same length,
+ you only need two codes (1+3). Hmm.
+ 10. In the tree reconstruction algorithm, Code = Code + Increment
+ only if BitLength(i) is not zero. (Pretty obvious.)
+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
+ 12. Note: length code 284 can represent 227-258, but length code 285
+ really is 258. The last length deserves its own, short code
+ since it gets used a lot in very redundant files. The length
+ 258 is special since 258 - 3 (the min match length) is 255.
+ 13. The literal/length and distance code bit lengths are read as a
+ single stream of lengths. It is possible (and advantageous) for
+ a repeat code (16, 17, or 18) to go across the boundary between
+ the two sets of lengths.
+ */
+
+
+void inflate_blocks_reset(s, z, c)
+inflate_blocks_statef *s;
+z_streamp z;
+uLongf *c;
+{
+ if (c != Z_NULL)
+ *c = s->check;
+ if (s->mode == BTREE || s->mode == DTREE)
+ ZFREE(z, s->sub.trees.blens);
+ if (s->mode == CODES)
+ inflate_codes_free(s->sub.decode.codes, z);
+ s->mode = TYPE;
+ s->bitk = 0;
+ s->bitb = 0;
+ s->read = s->write = s->window;
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0);
+ Tracev((stderr, "inflate: blocks reset\n"));
+}
+
+
+inflate_blocks_statef *inflate_blocks_new(z, c, w)
+z_streamp z;
+check_func c;
+uInt w;
+{
+ inflate_blocks_statef *s;
+
+ if ((s = (inflate_blocks_statef *)ZALLOC
+ (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
+ return s;
+ if ((s->hufts =
+ (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL)
+ {
+ ZFREE(z, s);
+ return Z_NULL;
+ }
+ if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
+ {
+ ZFREE(z, s->hufts);
+ ZFREE(z, s);
+ return Z_NULL;
+ }
+ s->end = s->window + w;
+ s->checkfn = c;
+ s->mode = TYPE;
+ Tracev((stderr, "inflate: blocks allocated\n"));
+ inflate_blocks_reset(s, z, Z_NULL);
+ return s;
+}
+
+
+int inflate_blocks(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+ uInt t; /* temporary storage */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+
+ /* copy input/output information to locals (UPDATE macro restores) */
+ LOAD
+
+ /* process input based on current state */
+ while (1) switch (s->mode)
+ {
+ case TYPE:
+ NEEDBITS(3)
+ t = (uInt)b & 7;
+ s->last = t & 1;
+ switch (t >> 1)
+ {
+ case 0: /* stored */
+ Tracev((stderr, "inflate: stored block%s\n",
+ s->last ? " (last)" : ""));
+ DUMPBITS(3)
+ t = k & 7; /* go to byte boundary */
+ DUMPBITS(t)
+ s->mode = LENS; /* get length of stored block */
+ break;
+ case 1: /* fixed */
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ s->last ? " (last)" : ""));
+ {
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+
+ inflate_trees_fixed(&bl, &bd, &tl, &td, z);
+ s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+ if (s->sub.decode.codes == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ }
+ DUMPBITS(3)
+ s->mode = CODES;
+ break;
+ case 2: /* dynamic */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ s->last ? " (last)" : ""));
+ DUMPBITS(3)
+ s->mode = TABLE;
+ break;
+ case 3: /* illegal */
+ DUMPBITS(3)
+ s->mode = BAD;
+ z->msg = (char*)"invalid block type";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ break;
+ case LENS:
+ NEEDBITS(32)
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ s->mode = BAD;
+ z->msg = (char*)"invalid stored block lengths";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ s->sub.left = (uInt)b & 0xffff;
+ b = k = 0; /* dump bits */
+ Tracev((stderr, "inflate: stored length %u\n", s->sub.left));
+ s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
+ break;
+ case STORED:
+ if (n == 0)
+ LEAVE
+ NEEDOUT
+ t = s->sub.left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ zmemcpy(q, p, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((s->sub.left -= t) != 0)
+ break;
+ Tracev((stderr, "inflate: stored end, %lu total out\n",
+ z->total_out + (q >= s->read ? q - s->read :
+ (s->end - s->read) + (q - s->window))));
+ s->mode = s->last ? DRY : TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14)
+ s->sub.trees.table = t = (uInt)b & 0x3fff;
+#ifndef PKZIP_BUG_WORKAROUND
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ s->mode = BAD;
+ z->msg = (char*)"too many length or distance symbols";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+#endif
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ DUMPBITS(14)
+ s->sub.trees.index = 0;
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ s->mode = BTREE;
+ case BTREE:
+ while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
+ {
+ NEEDBITS(3)
+ s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
+ DUMPBITS(3)
+ }
+ while (s->sub.trees.index < 19)
+ s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
+ s->sub.trees.bb = 7;
+ t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+ &s->sub.trees.tb, s->hufts, z);
+ if (t != Z_OK)
+ {
+ ZFREE(z, s->sub.trees.blens);
+ r = t;
+ if (r == Z_DATA_ERROR)
+ s->mode = BAD;
+ LEAVE
+ }
+ s->sub.trees.index = 0;
+ Tracev((stderr, "inflate: bits tree ok\n"));
+ s->mode = DTREE;
+ case DTREE:
+ while (t = s->sub.trees.table,
+ s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
+ {
+ inflate_huft *h;
+ uInt i, j, c;
+
+ t = s->sub.trees.bb;
+ NEEDBITS(t)
+ h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
+ t = h->bits;
+ c = h->base;
+ if (c < 16)
+ {
+ DUMPBITS(t)
+ s->sub.trees.blens[s->sub.trees.index++] = c;
+ }
+ else /* c == 16..18 */
+ {
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+ NEEDBITS(t + i)
+ DUMPBITS(t)
+ j += (uInt)b & inflate_mask[i];
+ DUMPBITS(i)
+ i = s->sub.trees.index;
+ t = s->sub.trees.table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ ZFREE(z, s->sub.trees.blens);
+ s->mode = BAD;
+ z->msg = (char*)"invalid bit length repeat";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
+ do {
+ s->sub.trees.blens[i++] = c;
+ } while (--j);
+ s->sub.trees.index = i;
+ }
+ }
+ s->sub.trees.tb = Z_NULL;
+ {
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+ inflate_codes_statef *c;
+
+ bl = 9; /* must be <= 9 for lookahead assumptions */
+ bd = 6; /* must be <= 9 for lookahead assumptions */
+ t = s->sub.trees.table;
+ t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+ s->sub.trees.blens, &bl, &bd, &tl, &td,
+ s->hufts, z);
+ ZFREE(z, s->sub.trees.blens);
+ if (t != Z_OK)
+ {
+ if (t == (uInt)Z_DATA_ERROR)
+ s->mode = BAD;
+ r = t;
+ LEAVE
+ }
+ Tracev((stderr, "inflate: trees ok\n"));
+ if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ s->sub.decode.codes = c;
+ }
+ s->mode = CODES;
+ case CODES:
+ UPDATE
+ if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+ return inflate_flush(s, z, r);
+ r = Z_OK;
+ inflate_codes_free(s->sub.decode.codes, z);
+ LOAD
+ Tracev((stderr, "inflate: codes end, %lu total out\n",
+ z->total_out + (q >= s->read ? q - s->read :
+ (s->end - s->read) + (q - s->window))));
+ if (!s->last)
+ {
+ s->mode = TYPE;
+ break;
+ }
+ s->mode = DRY;
+ case DRY:
+ FLUSH
+ if (s->read != s->write)
+ LEAVE
+ s->mode = DONE;
+ case DONE:
+ r = Z_STREAM_END;
+ LEAVE
+ case BAD:
+ r = Z_DATA_ERROR;
+ LEAVE
+ default:
+ r = Z_STREAM_ERROR;
+ LEAVE
+ }
+}
+
+
+int inflate_blocks_free(s, z)
+inflate_blocks_statef *s;
+z_streamp z;
+{
+ inflate_blocks_reset(s, z, Z_NULL);
+ ZFREE(z, s->window);
+ ZFREE(z, s->hufts);
+ ZFREE(z, s);
+ Tracev((stderr, "inflate: blocks freed\n"));
+ return Z_OK;
+}
+
+
+void inflate_set_dictionary(s, d, n)
+inflate_blocks_statef *s;
+const Bytef *d;
+uInt n;
+{
+ zmemcpy(s->window, d, n);
+ s->read = s->write = s->window + n;
+}
+
+
+/* Returns true if inflate is currently at the end of a block generated
+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH.
+ * IN assertion: s != Z_NULL
+ */
+int inflate_blocks_sync_point(s)
+inflate_blocks_statef *s;
+{
+ return s->mode == LENS;
+}
diff --git a/cfe/cfe/zlib/infblock.h b/cfe/cfe/zlib/infblock.h
new file mode 100644
index 0000000..bd25c80
--- /dev/null
+++ b/cfe/cfe/zlib/infblock.h
@@ -0,0 +1,39 @@
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_blocks_state;
+typedef struct inflate_blocks_state FAR inflate_blocks_statef;
+
+extern inflate_blocks_statef * inflate_blocks_new OF((
+ z_streamp z,
+ check_func c, /* check function */
+ uInt w)); /* window size */
+
+extern int inflate_blocks OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int)); /* initial return code */
+
+extern void inflate_blocks_reset OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ uLongf *)); /* check value on output */
+
+extern int inflate_blocks_free OF((
+ inflate_blocks_statef *,
+ z_streamp));
+
+extern void inflate_set_dictionary OF((
+ inflate_blocks_statef *s,
+ const Bytef *d, /* dictionary */
+ uInt n)); /* dictionary length */
+
+extern int inflate_blocks_sync_point OF((
+ inflate_blocks_statef *s));
diff --git a/cfe/cfe/zlib/infcodes.c b/cfe/cfe/zlib/infcodes.c
new file mode 100644
index 0000000..d4e5ee9
--- /dev/null
+++ b/cfe/cfe/zlib/infcodes.c
@@ -0,0 +1,257 @@
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#include "inffast.h"
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+ START, /* x: set up for LEN */
+ LEN, /* i: get length/literal/eob next */
+ LENEXT, /* i: getting length extra (have base) */
+ DIST, /* i: get distance next */
+ DISTEXT, /* i: getting distance extra */
+ COPY, /* o: copying bytes in window, waiting for space */
+ LIT, /* o: got literal, waiting for output space */
+ WASH, /* o: got eob, possibly still output waiting */
+ END, /* x: got eob and all data flushed */
+ BADCODE} /* x: got error */
+inflate_codes_mode;
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+ /* mode */
+ inflate_codes_mode mode; /* current inflate_codes mode */
+
+ /* mode dependent information */
+ uInt len;
+ union {
+ struct {
+ inflate_huft *tree; /* pointer into tree */
+ uInt need; /* bits needed */
+ } code; /* if LEN or DIST, where in tree */
+ uInt lit; /* if LIT, literal */
+ struct {
+ uInt get; /* bits to get for extra */
+ uInt dist; /* distance back to copy from */
+ } copy; /* if EXT or COPY, where and how much */
+ } sub; /* submode */
+
+ /* mode independent information */
+ Byte lbits; /* ltree bits decoded per branch */
+ Byte dbits; /* dtree bits decoder per branch */
+ inflate_huft *ltree; /* literal/length/eob tree */
+ inflate_huft *dtree; /* distance tree */
+
+};
+
+
+inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
+uInt bl, bd;
+inflate_huft *tl;
+inflate_huft *td; /* need separate declaration for Borland C++ */
+z_streamp z;
+{
+ inflate_codes_statef *c;
+
+ if ((c = (inflate_codes_statef *)
+ ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
+ {
+ c->mode = START;
+ c->lbits = (Byte)bl;
+ c->dbits = (Byte)bd;
+ c->ltree = tl;
+ c->dtree = td;
+ Tracev((stderr, "inflate: codes new\n"));
+ }
+ return c;
+}
+
+
+int inflate_codes(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+ uInt j; /* temporary storage */
+ inflate_huft *t; /* temporary pointer */
+ uInt e; /* extra bits or operation */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+ Bytef *f; /* pointer to copy strings from */
+ inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
+
+ /* copy input/output information to locals (UPDATE macro restores) */
+ LOAD
+
+ /* process input and output based on current state */
+ while (1) switch (c->mode)
+ { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+ case START: /* x: set up for LEN */
+#ifndef SLOW
+ if (m >= 258 && n >= 10)
+ {
+ UPDATE
+ r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+ LOAD
+ if (r != Z_OK)
+ {
+ c->mode = r == Z_STREAM_END ? WASH : BADCODE;
+ break;
+ }
+ }
+#endif /* !SLOW */
+ c->sub.code.need = c->lbits;
+ c->sub.code.tree = c->ltree;
+ c->mode = LEN;
+ case LEN: /* i: get length/literal/eob next */
+ j = c->sub.code.need;
+ NEEDBITS(j)
+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+ DUMPBITS(t->bits)
+ e = (uInt)(t->exop);
+ if (e == 0) /* literal */
+ {
+ c->sub.lit = t->base;
+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", t->base));
+ c->mode = LIT;
+ break;
+ }
+ if (e & 16) /* length */
+ {
+ c->sub.copy.get = e & 15;
+ c->len = t->base;
+ c->mode = LENEXT;
+ break;
+ }
+ if ((e & 64) == 0) /* next table */
+ {
+ c->sub.code.need = e;
+ c->sub.code.tree = t + t->base;
+ break;
+ }
+ if (e & 32) /* end of block */
+ {
+ Tracevv((stderr, "inflate: end of block\n"));
+ c->mode = WASH;
+ break;
+ }
+ c->mode = BADCODE; /* invalid code */
+ z->msg = (char*)"invalid literal/length code";
+ r = Z_DATA_ERROR;
+ LEAVE
+ case LENEXT: /* i: getting length extra (have base) */
+ j = c->sub.copy.get;
+ NEEDBITS(j)
+ c->len += (uInt)b & inflate_mask[j];
+ DUMPBITS(j)
+ c->sub.code.need = c->dbits;
+ c->sub.code.tree = c->dtree;
+ Tracevv((stderr, "inflate: length %u\n", c->len));
+ c->mode = DIST;
+ case DIST: /* i: get distance next */
+ j = c->sub.code.need;
+ NEEDBITS(j)
+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+ DUMPBITS(t->bits)
+ e = (uInt)(t->exop);
+ if (e & 16) /* distance */
+ {
+ c->sub.copy.get = e & 15;
+ c->sub.copy.dist = t->base;
+ c->mode = DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0) /* next table */
+ {
+ c->sub.code.need = e;
+ c->sub.code.tree = t + t->base;
+ break;
+ }
+ c->mode = BADCODE; /* invalid code */
+ z->msg = (char*)"invalid distance code";
+ r = Z_DATA_ERROR;
+ LEAVE
+ case DISTEXT: /* i: getting distance extra */
+ j = c->sub.copy.get;
+ NEEDBITS(j)
+ c->sub.copy.dist += (uInt)b & inflate_mask[j];
+ DUMPBITS(j)
+ Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
+ c->mode = COPY;
+ case COPY: /* o: copying bytes in window, waiting for space */
+#ifndef __TURBOC__ /* Turbo C bug for following expression */
+ f = (uInt)(q - s->window) < c->sub.copy.dist ?
+ s->end - (c->sub.copy.dist - (q - s->window)) :
+ q - c->sub.copy.dist;
+#else
+ f = q - c->sub.copy.dist;
+ if ((uInt)(q - s->window) < c->sub.copy.dist)
+ f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
+#endif
+ while (c->len)
+ {
+ NEEDOUT
+ OUTBYTE(*f++)
+ if (f == s->end)
+ f = s->window;
+ c->len--;
+ }
+ c->mode = START;
+ break;
+ case LIT: /* o: got literal, waiting for output space */
+ NEEDOUT
+ OUTBYTE(c->sub.lit)
+ c->mode = START;
+ break;
+ case WASH: /* o: got eob, possibly more output */
+ if (k > 7) /* return unused byte, if any */
+ {
+ Assert(k < 16, "inflate_codes grabbed too many bytes")
+ k -= 8;
+ n++;
+ p--; /* can always return one */
+ }
+ FLUSH
+ if (s->read != s->write)
+ LEAVE
+ c->mode = END;
+ case END:
+ r = Z_STREAM_END;
+ LEAVE
+ case BADCODE: /* x: got error */
+ r = Z_DATA_ERROR;
+ LEAVE
+ default:
+ r = Z_STREAM_ERROR;
+ LEAVE
+ }
+#ifdef NEED_DUMMY_RETURN
+ return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
+#endif
+}
+
+
+void inflate_codes_free(c, z)
+inflate_codes_statef *c;
+z_streamp z;
+{
+ ZFREE(z, c);
+ Tracev((stderr, "inflate: codes free\n"));
+}
diff --git a/cfe/cfe/zlib/infcodes.h b/cfe/cfe/zlib/infcodes.h
new file mode 100644
index 0000000..6c750d8
--- /dev/null
+++ b/cfe/cfe/zlib/infcodes.h
@@ -0,0 +1,27 @@
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_codes_state;
+typedef struct inflate_codes_state FAR inflate_codes_statef;
+
+extern inflate_codes_statef *inflate_codes_new OF((
+ uInt, uInt,
+ inflate_huft *, inflate_huft *,
+ z_streamp ));
+
+extern int inflate_codes OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int));
+
+extern void inflate_codes_free OF((
+ inflate_codes_statef *,
+ z_streamp ));
+
diff --git a/cfe/cfe/zlib/inffast.c b/cfe/cfe/zlib/inffast.c
new file mode 100644
index 0000000..61a78ee
--- /dev/null
+++ b/cfe/cfe/zlib/inffast.c
@@ -0,0 +1,170 @@
+/* inffast.c -- process literals and length/distance pairs fast
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#include "inffast.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* macros for bit input with no checking and for returning unused bytes */
+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;}
+
+/* Called with number of bytes left to write in window at least 258
+ (the maximum string length) and number of input bytes available
+ at least ten. The ten bytes are six bytes for the longest length/
+ distance pair plus four bytes for overloading the bit buffer. */
+
+int inflate_fast(bl, bd, tl, td, s, z)
+uInt bl, bd;
+inflate_huft *tl;
+inflate_huft *td; /* need separate declaration for Borland C++ */
+inflate_blocks_statef *s;
+z_streamp z;
+{
+ inflate_huft *t; /* temporary pointer */
+ uInt e; /* extra bits or operation */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+ uInt ml; /* mask for literal/length tree */
+ uInt md; /* mask for distance tree */
+ uInt c; /* bytes to copy */
+ uInt d; /* distance back to copy from */
+ Bytef *r; /* copy source pointer */
+
+ /* load input, output, bit values */
+ LOAD
+
+ /* initialize masks */
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ /* do until not enough input or output space for fast loop */
+ do { /* assume called with m >= 258 && n >= 10 */
+ /* get literal/length code */
+ GRABBITS(20) /* max bits for literal/length code */
+ if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
+ {
+ DUMPBITS(t->bits)
+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+ "inflate: * literal '%c'\n" :
+ "inflate: * literal 0x%02x\n", t->base));
+ *q++ = (Byte)t->base;
+ m--;
+ continue;
+ }
+ do {
+ DUMPBITS(t->bits)
+ if (e & 16)
+ {
+ /* get extra bits for length */
+ e &= 15;
+ c = t->base + ((uInt)b & inflate_mask[e]);
+ DUMPBITS(e)
+ Tracevv((stderr, "inflate: * length %u\n", c));
+
+ /* decode distance base of block to copy */
+ GRABBITS(15); /* max bits for distance code */
+ e = (t = td + ((uInt)b & md))->exop;
+ do {
+ DUMPBITS(t->bits)
+ if (e & 16)
+ {
+ /* get extra bits to add to distance base */
+ e &= 15;
+ GRABBITS(e) /* get extra bits (up to 13) */
+ d = t->base + ((uInt)b & inflate_mask[e]);
+ DUMPBITS(e)
+ Tracevv((stderr, "inflate: * distance %u\n", d));
+
+ /* do the copy */
+ m -= c;
+ if ((uInt)(q - s->window) >= d) /* offset before dest */
+ { /* just copy */
+ r = q - d;
+ *q++ = *r++; c--; /* minimum count is three, */
+ *q++ = *r++; c--; /* so unroll loop a little */
+ }
+ else /* else offset after destination */
+ {
+ e = d - (uInt)(q - s->window); /* bytes from offset to end */
+ r = s->end - e; /* pointer to offset */
+ if (c > e) /* if source crosses, */
+ {
+ c -= e; /* copy to end of window */
+ do {
+ *q++ = *r++;
+ } while (--e);
+ r = s->window; /* copy rest from start of window */
+ }
+ }
+ do { /* copy all or what's left */
+ *q++ = *r++;
+ } while (--c);
+ break;
+ }
+ else if ((e & 64) == 0)
+ {
+ t += t->base;
+ e = (t += ((uInt)b & inflate_mask[e]))->exop;
+ }
+ else
+ {
+ z->msg = (char*)"invalid distance code";
+ UNGRAB
+ UPDATE
+ return Z_DATA_ERROR;
+ }
+ } while (1);
+ break;
+ }
+ if ((e & 64) == 0)
+ {
+ t += t->base;
+ if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
+ {
+ DUMPBITS(t->bits)
+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+ "inflate: * literal '%c'\n" :
+ "inflate: * literal 0x%02x\n", t->base));
+ *q++ = (Byte)t->base;
+ m--;
+ break;
+ }
+ }
+ else if (e & 32)
+ {
+ Tracevv((stderr, "inflate: * end of block\n"));
+ UNGRAB
+ UPDATE
+ return Z_STREAM_END;
+ }
+ else
+ {
+ z->msg = (char*)"invalid literal/length code";
+ UNGRAB
+ UPDATE
+ return Z_DATA_ERROR;
+ }
+ } while (1);
+ } while (m >= 258 && n >= 10);
+
+ /* not enough input or output--restore pointers and return */
+ UNGRAB
+ UPDATE
+ return Z_OK;
+}
diff --git a/cfe/cfe/zlib/inffast.h b/cfe/cfe/zlib/inffast.h
new file mode 100644
index 0000000..8facec5
--- /dev/null
+++ b/cfe/cfe/zlib/inffast.h
@@ -0,0 +1,17 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+extern int inflate_fast OF((
+ uInt,
+ uInt,
+ inflate_huft *,
+ inflate_huft *,
+ inflate_blocks_statef *,
+ z_streamp ));
diff --git a/cfe/cfe/zlib/inffixed.h b/cfe/cfe/zlib/inffixed.h
new file mode 100644
index 0000000..77f7e76
--- /dev/null
+++ b/cfe/cfe/zlib/inffixed.h
@@ -0,0 +1,151 @@
+/* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by the maketree.c program
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+local uInt fixed_bl = 9;
+local uInt fixed_bd = 5;
+local inflate_huft fixed_tl[] = {
+ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
+ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
+ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
+ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
+ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
+ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
+ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
+ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
+ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
+ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
+ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
+ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
+ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
+ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
+ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
+ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
+ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
+ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
+ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
+ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
+ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
+ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
+ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
+ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
+ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
+ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
+ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
+ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
+ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
+ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
+ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
+ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
+ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
+ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
+ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
+ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
+ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
+ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
+ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
+ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
+ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
+ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
+ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
+ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
+ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
+ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
+ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
+ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
+ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
+ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
+ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
+ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
+ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
+ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
+ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
+ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
+ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
+ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
+ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
+ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
+ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
+ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
+ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
+ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
+ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
+ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
+ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
+ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
+ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
+ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
+ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
+ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
+ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
+ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
+ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
+ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
+ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
+ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
+ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
+ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
+ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
+ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
+ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
+ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
+ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
+ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
+ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
+ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
+ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
+ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
+ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
+ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
+ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
+ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
+ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
+ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
+ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
+ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
+ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
+ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
+ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
+ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
+ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
+ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
+ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
+ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
+ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
+ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
+ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
+ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
+ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
+ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
+ };
+local inflate_huft fixed_td[] = {
+ {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
+ {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
+ {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
+ {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
+ {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
+ {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
+ {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
+ {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
+ };
diff --git a/cfe/cfe/zlib/inflate.c b/cfe/cfe/zlib/inflate.c
new file mode 100644
index 0000000..32e9b8d
--- /dev/null
+++ b/cfe/cfe/zlib/inflate.c
@@ -0,0 +1,366 @@
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+
+struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
+
+typedef enum {
+ METHOD, /* waiting for method byte */
+ FLAG, /* waiting for flag byte */
+ DICT4, /* four dictionary check bytes to go */
+ DICT3, /* three dictionary check bytes to go */
+ DICT2, /* two dictionary check bytes to go */
+ DICT1, /* one dictionary check byte to go */
+ DICT0, /* waiting for inflateSetDictionary */
+ BLOCKS, /* decompressing blocks */
+ CHECK4, /* four check bytes to go */
+ CHECK3, /* three check bytes to go */
+ CHECK2, /* two check bytes to go */
+ CHECK1, /* one check byte to go */
+ DONE, /* finished check, done */
+ BAD} /* got an error--stay here */
+inflate_mode;
+
+/* inflate private state */
+struct internal_state {
+
+ /* mode */
+ inflate_mode mode; /* current inflate mode */
+
+ /* mode dependent information */
+ union {
+ uInt method; /* if FLAGS, method byte */
+ struct {
+ uLong was; /* computed check value */
+ uLong need; /* stream check value */
+ } check; /* if CHECK, check values to compare */
+ uInt marker; /* if BAD, inflateSync's marker bytes count */
+ } sub; /* submode */
+
+ /* mode independent information */
+ int nowrap; /* flag for no wrapper */
+ uInt wbits; /* log2(window size) (8..15, defaults to 15) */
+ inflate_blocks_statef
+ *blocks; /* current inflate_blocks state */
+
+};
+
+
+int ZEXPORT inflateReset(z)
+z_streamp z;
+{
+ if (z == Z_NULL || z->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ z->total_in = z->total_out = 0;
+ z->msg = Z_NULL;
+ z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
+ inflate_blocks_reset(z->state->blocks, z, Z_NULL);
+ Tracev((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+
+int ZEXPORT inflateEnd(z)
+z_streamp z;
+{
+ if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
+ return Z_STREAM_ERROR;
+ if (z->state->blocks != Z_NULL)
+ inflate_blocks_free(z->state->blocks, z);
+ ZFREE(z, z->state);
+ z->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+
+int ZEXPORT inflateInit2_(z, w, version, stream_size)
+z_streamp z;
+int w;
+const char *version;
+int stream_size;
+{
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != sizeof(z_stream))
+ return Z_VERSION_ERROR;
+
+ /* initialize state */
+ if (z == Z_NULL)
+ return Z_STREAM_ERROR;
+ z->msg = Z_NULL;
+ if (z->zalloc == Z_NULL)
+ {
+ z->zalloc = zcalloc;
+ z->opaque = (voidpf)0;
+ }
+ if (z->zfree == Z_NULL) z->zfree = zcfree;
+ if ((z->state = (struct internal_state FAR *)
+ ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
+ return Z_MEM_ERROR;
+ z->state->blocks = Z_NULL;
+
+ /* handle undocumented nowrap option (no zlib header or check) */
+ z->state->nowrap = 0;
+ if (w < 0)
+ {
+ w = - w;
+ z->state->nowrap = 1;
+ }
+
+ /* set window size */
+ if (w < 8 || w > 15)
+ {
+ inflateEnd(z);
+ return Z_STREAM_ERROR;
+ }
+ z->state->wbits = (uInt)w;
+
+ /* create inflate_blocks state */
+ if ((z->state->blocks =
+ inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
+ == Z_NULL)
+ {
+ inflateEnd(z);
+ return Z_MEM_ERROR;
+ }
+ Tracev((stderr, "inflate: allocated\n"));
+
+ /* reset state */
+ inflateReset(z);
+ return Z_OK;
+}
+
+
+int ZEXPORT inflateInit_(z, version, stream_size)
+z_streamp z;
+const char *version;
+int stream_size;
+{
+ return inflateInit2_(z, DEF_WBITS, version, stream_size);
+}
+
+
+#define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+int ZEXPORT inflate(z, f)
+z_streamp z;
+int f;
+{
+ int r;
+ uInt b;
+
+ if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
+ return Z_STREAM_ERROR;
+ f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
+ r = Z_BUF_ERROR;
+ while (1) switch (z->state->mode)
+ {
+ case METHOD:
+ NEEDBYTE
+ if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"unknown compression method";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"invalid window size";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ z->state->mode = FLAG;
+ case FLAG:
+ NEEDBYTE
+ b = NEXTBYTE;
+ if (((z->state->sub.method << 8) + b) % 31)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"incorrect header check";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ Tracev((stderr, "inflate: zlib header ok\n"));
+ if (!(b & PRESET_DICT))
+ {
+ z->state->mode = BLOCKS;
+ break;
+ }
+ z->state->mode = DICT4;
+ case DICT4:
+ NEEDBYTE
+ z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+ z->state->mode = DICT3;
+ case DICT3:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+ z->state->mode = DICT2;
+ case DICT2:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+ z->state->mode = DICT1;
+ case DICT1:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE;
+ z->adler = z->state->sub.check.need;
+ z->state->mode = DICT0;
+ return Z_NEED_DICT;
+ case DICT0:
+ z->state->mode = BAD;
+ z->msg = (char*)"need dictionary";
+ z->state->sub.marker = 0; /* can try inflateSync */
+ return Z_STREAM_ERROR;
+ case BLOCKS:
+ r = inflate_blocks(z->state->blocks, z, r);
+ if (r == Z_DATA_ERROR)
+ {
+ z->state->mode = BAD;
+ z->state->sub.marker = 0; /* can try inflateSync */
+ break;
+ }
+ if (r == Z_OK)
+ r = f;
+ if (r != Z_STREAM_END)
+ return r;
+ r = f;
+ inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+ if (z->state->nowrap)
+ {
+ z->state->mode = DONE;
+ break;
+ }
+ z->state->mode = CHECK4;
+ case CHECK4:
+ NEEDBYTE
+ z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+ z->state->mode = CHECK3;
+ case CHECK3:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+ z->state->mode = CHECK2;
+ case CHECK2:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+ z->state->mode = CHECK1;
+ case CHECK1:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE;
+
+ if (z->state->sub.check.was != z->state->sub.check.need)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"incorrect data check";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ Tracev((stderr, "inflate: zlib check ok\n"));
+ z->state->mode = DONE;
+ case DONE:
+ return Z_STREAM_END;
+ case BAD:
+ return Z_DATA_ERROR;
+ default:
+ return Z_STREAM_ERROR;
+ }
+#ifdef NEED_DUMMY_RETURN
+ return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
+#endif
+}
+
+
+int ZEXPORT inflateSetDictionary(z, dictionary, dictLength)
+z_streamp z;
+const Bytef *dictionary;
+uInt dictLength;
+{
+ uInt length = dictLength;
+
+ if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
+ return Z_STREAM_ERROR;
+
+ if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
+ z->adler = 1L;
+
+ if (length >= ((uInt)1<<z->state->wbits))
+ {
+ length = (1<<z->state->wbits)-1;
+ dictionary += dictLength - length;
+ }
+ inflate_set_dictionary(z->state->blocks, dictionary, length);
+ z->state->mode = BLOCKS;
+ return Z_OK;
+}
+
+
+int ZEXPORT inflateSync(z)
+z_streamp z;
+{
+ uInt n; /* number of bytes to look at */
+ Bytef *p; /* pointer to bytes */
+ uInt m; /* number of marker bytes found in a row */
+ uLong r, w; /* temporaries to save total_in and total_out */
+
+ /* set up */
+ if (z == Z_NULL || z->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ if (z->state->mode != BAD)
+ {
+ z->state->mode = BAD;
+ z->state->sub.marker = 0;
+ }
+ if ((n = z->avail_in) == 0)
+ return Z_BUF_ERROR;
+ p = z->next_in;
+ m = z->state->sub.marker;
+
+ /* search */
+ while (n && m < 4)
+ {
+ static const Byte mark[4] = {0, 0, 0xff, 0xff};
+ if (*p == mark[m])
+ m++;
+ else if (*p)
+ m = 0;
+ else
+ m = 4 - m;
+ p++, n--;
+ }
+
+ /* restore */
+ z->total_in += p - z->next_in;
+ z->next_in = p;
+ z->avail_in = n;
+ z->state->sub.marker = m;
+
+ /* return no joy or set up to restart on a new block */
+ if (m != 4)
+ return Z_DATA_ERROR;
+ r = z->total_in; w = z->total_out;
+ inflateReset(z);
+ z->total_in = r; z->total_out = w;
+ z->state->mode = BLOCKS;
+ return Z_OK;
+}
+
+
+/* Returns true if inflate is currently at the end of a block generated
+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
+ * but removes the length bytes of the resulting empty stored block. When
+ * decompressing, PPP checks that at the end of input packet, inflate is
+ * waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(z)
+z_streamp z;
+{
+ if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL)
+ return Z_STREAM_ERROR;
+ return inflate_blocks_sync_point(z->state->blocks);
+}
diff --git a/cfe/cfe/zlib/inftrees.c b/cfe/cfe/zlib/inftrees.c
new file mode 100644
index 0000000..ef1e0b6
--- /dev/null
+++ b/cfe/cfe/zlib/inftrees.c
@@ -0,0 +1,455 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#if !defined(BUILDFIXED) && !defined(STDC)
+# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */
+#endif
+
+const char inflate_copyright[] =
+ " inflate 1.1.3 Copyright 1995-1998 Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+struct internal_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+
+local int huft_build OF((
+ uIntf *, /* code lengths in bits */
+ uInt, /* number of codes */
+ uInt, /* number of "simple" codes */
+ const uIntf *, /* list of base values for non-simple codes */
+ const uIntf *, /* list of extra bits for non-simple codes */
+ inflate_huft * FAR*,/* result: starting table */
+ uIntf *, /* maximum lookup bits (returns actual) */
+ inflate_huft *, /* space for trees */
+ uInt *, /* hufts used in space */
+ uIntf * )); /* space for values */
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ /* see note #13 above about 258 */
+local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
+local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577};
+local const uInt cpdext[30] = { /* Extra bits for distance codes */
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+/*
+ Huffman code decoding is performed using a multi-level table lookup.
+ The fastest way to decode is to simply build a lookup table whose
+ size is determined by the longest code. However, the time it takes
+ to build this table can also be a factor if the data being decoded
+ is not very long. The most common codes are necessarily the
+ shortest codes, so those codes dominate the decoding time, and hence
+ the speed. The idea is you can have a shorter table that decodes the
+ shorter, more probable codes, and then point to subsidiary tables for
+ the longer codes. The time it costs to decode the longer codes is
+ then traded against the time it takes to make longer tables.
+
+ This results of this trade are in the variables lbits and dbits
+ below. lbits is the number of bits the first level table for literal/
+ length codes can decode in one step, and dbits is the same thing for
+ the distance codes. Subsequent tables are also less than or equal to
+ those sizes. These values may be adjusted either when all of the
+ codes are shorter than that, in which case the longest code length in
+ bits is used, or when the shortest code is *longer* than the requested
+ table size, in which case the length of the shortest code in bits is
+ used.
+
+ There are two different values for the two tables, since they code a
+ different number of possibilities each. The literal/length table
+ codes 286 possible values, or in a flat code, a little over eight
+ bits. The distance table codes 30 possible values, or a little less
+ than five bits, flat. The optimum values for speed end up being
+ about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+ The optimum values may differ though from machine to machine, and
+ possibly even between compilers. Your mileage may vary.
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+#define BMAX 15 /* maximum bit length of any code */
+
+local int huft_build(b, n, s, d, e, t, m, hp, hn, v)
+uIntf *b; /* code lengths in bits (all assumed <= BMAX) */
+uInt n; /* number of codes (assumed <= 288) */
+uInt s; /* number of simple-valued codes (0..s-1) */
+const uIntf *d; /* list of base values for non-simple codes */
+const uIntf *e; /* list of extra bits for non-simple codes */
+inflate_huft * FAR *t; /* result: starting table */
+uIntf *m; /* maximum lookup bits, returns actual */
+inflate_huft *hp; /* space for trees */
+uInt *hn; /* hufts used in space */
+uIntf *v; /* working area: values in order of bit length */
+/* Given a list of code lengths and a maximum table size, make a set of
+ tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ if the given code set is incomplete (the tables are still built in this
+ case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+ lengths), or Z_MEM_ERROR if not enough memory. */
+{
+
+ uInt a; /* counter for codes of length k */
+ uInt c[BMAX+1]; /* bit length count table */
+ uInt f; /* i repeats in table every f entries */
+ int g; /* maximum code length */
+ int h; /* table level */
+ register uInt i; /* counter, current code */
+ register uInt j; /* counter */
+ register int k; /* number of bits in current code */
+ int l; /* bits per table (returned in m) */
+ uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */
+ register uIntf *p; /* pointer into c[], b[], or v[] */
+ inflate_huft *q; /* points to current table */
+ struct inflate_huft_s r; /* table entry for structure assignment */
+ inflate_huft *u[BMAX]; /* table stack */
+ register int w; /* bits before this table == (l * h) */
+ uInt x[BMAX+1]; /* bit offsets, then code stack */
+ uIntf *xp; /* pointer into x */
+ int y; /* number of dummy codes added */
+ uInt z; /* number of entries in current table */
+
+
+ /* Generate counts for each bit length */
+ p = c;
+#define C0 *p++ = 0;
+#define C2 C0 C0 C0 C0
+#define C4 C2 C2 C2 C2
+ C4 /* clear c[]--assume BMAX+1 is 16 */
+ p = b; i = n;
+ do {
+ c[*p++]++; /* assume all entries <= BMAX */
+ } while (--i);
+ if (c[0] == n) /* null input--all zero length codes */
+ {
+ *t = (inflate_huft *)Z_NULL;
+ *m = 0;
+ return Z_OK;
+ }
+
+
+ /* Find minimum and maximum length, bound *m by those */
+ l = *m;
+ for (j = 1; j <= BMAX; j++)
+ if (c[j])
+ break;
+ k = j; /* minimum code length */
+ if ((uInt)l < j)
+ l = j;
+ for (i = BMAX; i; i--)
+ if (c[i])
+ break;
+ g = i; /* maximum code length */
+ if ((uInt)l > i)
+ l = i;
+ *m = l;
+
+
+ /* Adjust last length count to fill out codes, if needed */
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ if ((y -= c[j]) < 0)
+ return Z_DATA_ERROR;
+ if ((y -= c[i]) < 0)
+ return Z_DATA_ERROR;
+ c[i] += y;
+
+
+ /* Generate starting offsets into the value table for each length */
+ x[1] = j = 0;
+ p = c + 1; xp = x + 2;
+ while (--i) { /* note that i == g from above */
+ *xp++ = (j += *p++);
+ }
+
+
+ /* Make a table of values in order of bit lengths */
+ p = b; i = 0;
+ do {
+ if ((j = *p++) != 0)
+ v[x[j]++] = i;
+ } while (++i < n);
+ n = x[g]; /* set n to length of v */
+
+
+ /* Generate the Huffman codes and for each, make the table entries */
+ x[0] = i = 0; /* first Huffman code is zero */
+ p = v; /* grab values in bit order */
+ h = -1; /* no tables yet--level -1 */
+ w = -l; /* bits decoded == (l * h) */
+ u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */
+ q = (inflate_huft *)Z_NULL; /* ditto */
+ z = 0; /* ditto */
+
+ /* go through the bit lengths (k already is bits in shortest code) */
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a--)
+ {
+ /* here i is the Huffman code of length k bits for value *p */
+ /* make tables up to required level */
+ while (k > w + l)
+ {
+ h++;
+ w += l; /* previous table always l bits */
+
+ /* compute minimum size table less than or equal to l bits */
+ z = g - w;
+ z = z > (uInt)l ? l : z; /* table size upper limit */
+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
+ { /* too few codes for k-w bit table */
+ f -= a + 1; /* deduct codes from patterns left */
+ xp = c + k;
+ if (j < z)
+ while (++j < z) /* try smaller tables up to z bits */
+ {
+ if ((f <<= 1) <= *++xp)
+ break; /* enough codes to use up j bits */
+ f -= *xp; /* else deduct codes from patterns */
+ }
+ }
+ z = 1 << j; /* table entries for j-bit table */
+
+ /* allocate new table */
+ if (*hn + z > MANY) /* (note: doesn't matter for fixed) */
+ return Z_MEM_ERROR; /* not enough memory */
+ u[h] = q = hp + *hn;
+ *hn += z;
+
+ /* connect to last table, if there is one */
+ if (h)
+ {
+ x[h] = i; /* save pattern for backing up */
+ r.bits = (Byte)l; /* bits to dump before this table */
+ r.exop = (Byte)j; /* bits in this table */
+ j = i >> (w - l);
+ r.base = (uInt)(q - u[h-1] - j); /* offset to this table */
+ u[h-1][j] = r; /* connect to last table */
+ }
+ else
+ *t = q; /* first table is returned result */
+ }
+
+ /* set up table entry in r */
+ r.bits = (Byte)(k - w);
+ if (p >= v + n)
+ r.exop = 128 + 64; /* out of values--invalid code */
+ else if (*p < s)
+ {
+ r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */
+ r.base = *p++; /* simple code is just the value */
+ }
+ else
+ {
+ r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
+ r.base = d[*p++ - s];
+ }
+
+ /* fill code-like entries with r */
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ q[j] = r;
+
+ /* backwards increment the k-bit code i */
+ for (j = 1 << (k - 1); i & j; j >>= 1)
+ i ^= j;
+ i ^= j;
+
+ /* backup over finished tables */
+ mask = (1 << w) - 1; /* needed on HP, cc -O bug */
+ while ((i & mask) != x[h])
+ {
+ h--; /* don't need to update q */
+ w -= l;
+ mask = (1 << w) - 1;
+ }
+ }
+ }
+
+
+ /* Return Z_BUF_ERROR if we were given an incomplete table */
+ return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+}
+
+
+int inflate_trees_bits(c, bb, tb, hp, z)
+uIntf *c; /* 19 code lengths */
+uIntf *bb; /* bits tree desired/actual depth */
+inflate_huft * FAR *tb; /* bits tree result */
+inflate_huft *hp; /* space for trees */
+z_streamp z; /* for messages */
+{
+ int r;
+ uInt hn = 0; /* hufts used in space */
+ uIntf *v; /* work area for huft_build */
+
+ if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
+ return Z_MEM_ERROR;
+ r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL,
+ tb, bb, hp, &hn, v);
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed dynamic bit lengths tree";
+ else if (r == Z_BUF_ERROR || *bb == 0)
+ {
+ z->msg = (char*)"incomplete dynamic bit lengths tree";
+ r = Z_DATA_ERROR;
+ }
+ ZFREE(z, v);
+ return r;
+}
+
+
+int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z)
+uInt nl; /* number of literal/length codes */
+uInt nd; /* number of distance codes */
+uIntf *c; /* that many (total) code lengths */
+uIntf *bl; /* literal desired/actual bit depth */
+uIntf *bd; /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+inflate_huft *hp; /* space for trees */
+z_streamp z; /* for messages */
+{
+ int r;
+ uInt hn = 0; /* hufts used in space */
+ uIntf *v; /* work area for huft_build */
+
+ /* allocate work area */
+ if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+ return Z_MEM_ERROR;
+
+ /* build literal/length tree */
+ r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
+ if (r != Z_OK || *bl == 0)
+ {
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed literal/length tree";
+ else if (r != Z_MEM_ERROR)
+ {
+ z->msg = (char*)"incomplete literal/length tree";
+ r = Z_DATA_ERROR;
+ }
+ ZFREE(z, v);
+ return r;
+ }
+
+ /* build distance tree */
+ r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
+ if (r != Z_OK || (*bd == 0 && nl > 257))
+ {
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed distance tree";
+ else if (r == Z_BUF_ERROR) {
+#ifdef PKZIP_BUG_WORKAROUND
+ r = Z_OK;
+ }
+#else
+ z->msg = (char*)"incomplete distance tree";
+ r = Z_DATA_ERROR;
+ }
+ else if (r != Z_MEM_ERROR)
+ {
+ z->msg = (char*)"empty distance tree with lengths";
+ r = Z_DATA_ERROR;
+ }
+ ZFREE(z, v);
+ return r;
+#endif
+ }
+
+ /* done */
+ ZFREE(z, v);
+ return Z_OK;
+}
+
+
+/* build fixed tables only once--keep them here */
+#ifdef BUILDFIXED
+local int fixed_built = 0;
+#define FIXEDH 544 /* number of hufts used by fixed tables */
+local inflate_huft fixed_mem[FIXEDH];
+local uInt fixed_bl;
+local uInt fixed_bd;
+local inflate_huft *fixed_tl;
+local inflate_huft *fixed_td;
+#else
+#include "inffixed.h"
+#endif
+
+
+int inflate_trees_fixed(bl, bd, tl, td, z)
+uIntf *bl; /* literal desired/actual bit depth */
+uIntf *bd; /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+z_streamp z; /* for memory allocation */
+{
+#ifdef BUILDFIXED
+ /* build fixed tables if not already */
+ if (!fixed_built)
+ {
+ int k; /* temporary variable */
+ uInt f = 0; /* number of hufts used in fixed_mem */
+ uIntf *c; /* length list for huft_build */
+ uIntf *v; /* work area for huft_build */
+
+ /* allocate memory */
+ if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+ return Z_MEM_ERROR;
+ if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+ {
+ ZFREE(z, c);
+ return Z_MEM_ERROR;
+ }
+
+ /* literal table */
+ for (k = 0; k < 144; k++)
+ c[k] = 8;
+ for (; k < 256; k++)
+ c[k] = 9;
+ for (; k < 280; k++)
+ c[k] = 7;
+ for (; k < 288; k++)
+ c[k] = 8;
+ fixed_bl = 9;
+ huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl,
+ fixed_mem, &f, v);
+
+ /* distance table */
+ for (k = 0; k < 30; k++)
+ c[k] = 5;
+ fixed_bd = 5;
+ huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd,
+ fixed_mem, &f, v);
+
+ /* done */
+ ZFREE(z, v);
+ ZFREE(z, c);
+ fixed_built = 1;
+ }
+#endif
+ *bl = fixed_bl;
+ *bd = fixed_bd;
+ *tl = fixed_tl;
+ *td = fixed_td;
+ return Z_OK;
+}
diff --git a/cfe/cfe/zlib/inftrees.h b/cfe/cfe/zlib/inftrees.h
new file mode 100644
index 0000000..85853e0
--- /dev/null
+++ b/cfe/cfe/zlib/inftrees.h
@@ -0,0 +1,58 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+ that have 16-bit pointers (e.g. PC's in the small or medium model). */
+
+typedef struct inflate_huft_s FAR inflate_huft;
+
+struct inflate_huft_s {
+ union {
+ struct {
+ Byte Exop; /* number of extra bits or operation */
+ Byte Bits; /* number of bits in this code or subcode */
+ } what;
+ uInt pad; /* pad structure to a power of 2 (4 bytes for */
+ } word; /* 16-bit, 8 bytes for 32-bit int's) */
+ uInt base; /* literal, length base, distance base,
+ or table offset */
+};
+
+/* Maximum size of dynamic tree. The maximum found in a long but non-
+ exhaustive search was 1004 huft structures (850 for length/literals
+ and 154 for distances, the latter actually the result of an
+ exhaustive search). The actual maximum is not known, but the
+ value below is more than safe. */
+#define MANY 1440
+
+extern int inflate_trees_bits OF((
+ uIntf *, /* 19 code lengths */
+ uIntf *, /* bits tree desired/actual depth */
+ inflate_huft * FAR *, /* bits tree result */
+ inflate_huft *, /* space for trees */
+ z_streamp)); /* for messages */
+
+extern int inflate_trees_dynamic OF((
+ uInt, /* number of literal/length codes */
+ uInt, /* number of distance codes */
+ uIntf *, /* that many (total) code lengths */
+ uIntf *, /* literal desired/actual bit depth */
+ uIntf *, /* distance desired/actual bit depth */
+ inflate_huft * FAR *, /* literal/length tree result */
+ inflate_huft * FAR *, /* distance tree result */
+ inflate_huft *, /* space for trees */
+ z_streamp)); /* for messages */
+
+extern int inflate_trees_fixed OF((
+ uIntf *, /* literal desired/actual bit depth */
+ uIntf *, /* distance desired/actual bit depth */
+ inflate_huft * FAR *, /* literal/length tree result */
+ inflate_huft * FAR *, /* distance tree result */
+ z_streamp)); /* for memory allocation */
diff --git a/cfe/cfe/zlib/infutil.c b/cfe/cfe/zlib/infutil.c
new file mode 100644
index 0000000..824dab5
--- /dev/null
+++ b/cfe/cfe/zlib/infutil.c
@@ -0,0 +1,87 @@
+/* inflate_util.c -- data and routines common to blocks and codes
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* And'ing with mask[n] masks the lower n bits */
+uInt inflate_mask[17] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+
+/* copy as much as possible from the sliding window to the output area */
+int inflate_flush(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+ uInt n;
+ Bytef *p;
+ Bytef *q;
+
+ /* local copies of source and destination pointers */
+ p = z->next_out;
+ q = s->read;
+
+ /* compute number of bytes to copy as far as end of window */
+ n = (uInt)((q <= s->write ? s->write : s->end) - q);
+ if (n > z->avail_out) n = z->avail_out;
+ if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+ /* update counters */
+ z->avail_out -= n;
+ z->total_out += n;
+
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+ /* copy as far as end of window */
+ zmemcpy(p, q, n);
+ p += n;
+ q += n;
+
+ /* see if more to copy at beginning of window */
+ if (q == s->end)
+ {
+ /* wrap pointers */
+ q = s->window;
+ if (s->write == s->end)
+ s->write = s->window;
+
+ /* compute bytes to copy */
+ n = (uInt)(s->write - q);
+ if (n > z->avail_out) n = z->avail_out;
+ if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+ /* update counters */
+ z->avail_out -= n;
+ z->total_out += n;
+
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+ /* copy */
+ zmemcpy(p, q, n);
+ p += n;
+ q += n;
+ }
+
+ /* update pointers */
+ z->next_out = p;
+ s->read = q;
+
+ /* done */
+ return r;
+}
diff --git a/cfe/cfe/zlib/infutil.h b/cfe/cfe/zlib/infutil.h
new file mode 100644
index 0000000..99d1135
--- /dev/null
+++ b/cfe/cfe/zlib/infutil.h
@@ -0,0 +1,98 @@
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFUTIL_H
+#define _INFUTIL_H
+
+typedef enum {
+ TYPE, /* get type bits (3, including end bit) */
+ LENS, /* get lengths for stored */
+ STORED, /* processing stored block */
+ TABLE, /* get table lengths */
+ BTREE, /* get bit lengths tree for a dynamic block */
+ DTREE, /* get length, distance trees for a dynamic block */
+ CODES, /* processing fixed or dynamic block */
+ DRY, /* output remaining window bytes */
+ DONE, /* finished last block, done */
+ BAD} /* got a data error--stuck here */
+inflate_block_mode;
+
+/* inflate blocks semi-private state */
+struct inflate_blocks_state {
+
+ /* mode */
+ inflate_block_mode mode; /* current inflate_block mode */
+
+ /* mode dependent information */
+ union {
+ uInt left; /* if STORED, bytes left to copy */
+ struct {
+ uInt table; /* table lengths (14 bits) */
+ uInt index; /* index into blens (or border) */
+ uIntf *blens; /* bit lengths of codes */
+ uInt bb; /* bit length tree depth */
+ inflate_huft *tb; /* bit length decoding tree */
+ } trees; /* if DTREE, decoding info for trees */
+ struct {
+ inflate_codes_statef
+ *codes;
+ } decode; /* if CODES, current state */
+ } sub; /* submode */
+ uInt last; /* true if this block is the last block */
+
+ /* mode independent information */
+ uInt bitk; /* bits in bit buffer */
+ uLong bitb; /* bit buffer */
+ inflate_huft *hufts; /* single malloc for tree space */
+ Bytef *window; /* sliding window */
+ Bytef *end; /* one byte after sliding window */
+ Bytef *read; /* window read pointer */
+ Bytef *write; /* window write pointer */
+ check_func checkfn; /* check function */
+ uLong check; /* check on output */
+
+};
+
+
+/* defines for inflate input/output */
+/* update pointers and return */
+#define UPDBITS {s->bitb=b;s->bitk=k;}
+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
+#define UPDOUT {s->write=q;}
+#define UPDATE {UPDBITS UPDIN UPDOUT}
+#define LEAVE {UPDATE return inflate_flush(s,z,r);}
+/* get bytes and bits */
+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
+#define NEXTBYTE (n--,*p++)
+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(j) {b>>=(j);k-=(j);}
+/* output bytes */
+#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
+#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
+#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
+/* load local pointers */
+#define LOAD {LOADIN LOADOUT}
+
+/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
+extern uInt inflate_mask[17];
+
+/* copy as much as possible from the sliding window to the output area */
+extern int inflate_flush OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int));
+
+struct internal_state {int dummy;}; /* for buggy compilers */
+
+#endif
diff --git a/cfe/cfe/zlib/maketree.c b/cfe/cfe/zlib/maketree.c
new file mode 100644
index 0000000..949d786
--- /dev/null
+++ b/cfe/cfe/zlib/maketree.c
@@ -0,0 +1,85 @@
+/* maketree.c -- make inffixed.h table for decoding fixed codes
+ * Copyright (C) 1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* This program is included in the distribution for completeness.
+ You do not need to compile or run this program since inffixed.h
+ is already included in the distribution. To use this program
+ you need to compile zlib with BUILDFIXED defined and then compile
+ and link this program with the zlib library. Then the output of
+ this program can be piped to inffixed.h. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "zutil.h"
+#include "inftrees.h"
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* generate initialization table for an inflate_huft structure array */
+void maketree(uInt b, inflate_huft *t)
+{
+ int i, e;
+
+ i = 0;
+ while (1)
+ {
+ e = t[i].exop;
+ if (e && (e & (16+64)) == 0) /* table pointer */
+ {
+ fprintf(stderr, "maketree: cannot initialize sub-tables!\n");
+ exit(1);
+ }
+ if (i % 4 == 0)
+ printf("\n ");
+ printf(" {{{%u,%u}},%u}", t[i].exop, t[i].bits, t[i].base);
+ if (++i == (1<<b))
+ break;
+ putchar(',');
+ }
+ puts("");
+}
+
+/* create the fixed tables in C initialization syntax */
+void main(void)
+{
+ int r;
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+ z_stream z;
+
+ z.zalloc = zcalloc;
+ z.opaque = (voidpf)0;
+ z.zfree = zcfree;
+ r = inflate_trees_fixed(&bl, &bd, &tl, &td, &z);
+ if (r)
+ {
+ fprintf(stderr, "inflate_trees_fixed error %d\n", r);
+ return;
+ }
+ puts("/* inffixed.h -- table for decoding fixed codes");
+ puts(" * Generated automatically by the maketree.c program");
+ puts(" */");
+ puts("");
+ puts("/* WARNING: this file should *not* be used by applications. It is");
+ puts(" part of the implementation of the compression library and is");
+ puts(" subject to change. Applications should only use zlib.h.");
+ puts(" */");
+ puts("");
+ printf("local uInt fixed_bl = %d;\n", bl);
+ printf("local uInt fixed_bd = %d;\n", bd);
+ printf("local inflate_huft fixed_tl[] = {");
+ maketree(bl, tl);
+ puts(" };");
+ printf("local inflate_huft fixed_td[] = {");
+ maketree(bd, td);
+ puts(" };");
+}
diff --git a/cfe/cfe/zlib/minigzip.c b/cfe/cfe/zlib/minigzip.c
new file mode 100644
index 0000000..f28ad8d
--- /dev/null
+++ b/cfe/cfe/zlib/minigzip.c
@@ -0,0 +1,320 @@
+/* minigzip.c -- simulate gzip using the zlib compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * minigzip is a minimal implementation of the gzip utility. This is
+ * only an example of using zlib and isn't meant to replace the
+ * full-featured gzip. No attempt is made to deal with file systems
+ * limiting names to 14 or 8+3 characters, etc... Error checking is
+ * very limited. So use minigzip only for testing; use gzip for the
+ * real thing. On MSDOS, use only on file names without extension
+ * or in pipe mode.
+ */
+
+/* @(#) $Id: minigzip.c,v 1.1 2001/11/09 01:48:02 mpl Exp $ */
+
+#include <stdio.h>
+#include "zlib.h"
+
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+#else
+ extern void exit OF((int));
+#endif
+
+#ifdef USE_MMAP
+# include <sys/types.h>
+# include <sys/mman.h>
+# include <sys/stat.h>
+#endif
+
+#if defined(MSDOS) || defined(OS2) || defined(WIN32)
+# include <fcntl.h>
+# include <io.h>
+# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+# define SET_BINARY_MODE(file)
+#endif
+
+#ifdef VMS
+# define unlink delete
+# define GZ_SUFFIX "-gz"
+#endif
+#ifdef RISCOS
+# define unlink remove
+# define GZ_SUFFIX "-gz"
+# define fileno(file) file->__file
+#endif
+#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+# include <unix.h> /* for fileno */
+#endif
+
+#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
+ extern int unlink OF((const char *));
+#endif
+
+#ifndef GZ_SUFFIX
+# define GZ_SUFFIX ".gz"
+#endif
+#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
+
+#define BUFLEN 16384
+#define MAX_NAME_LEN 1024
+
+#ifdef MAXSEG_64K
+# define local static
+ /* Needed for systems with limitation on stack size. */
+#else
+# define local
+#endif
+
+char *prog;
+
+void error OF((const char *msg));
+void gz_compress OF((FILE *in, gzFile out));
+#ifdef USE_MMAP
+int gz_compress_mmap OF((FILE *in, gzFile out));
+#endif
+void gz_uncompress OF((gzFile in, FILE *out));
+void file_compress OF((char *file, char *mode));
+void file_uncompress OF((char *file));
+int main OF((int argc, char *argv[]));
+
+/* ===========================================================================
+ * Display error message and exit
+ */
+void error(msg)
+ const char *msg;
+{
+ fprintf(stderr, "%s: %s\n", prog, msg);
+ exit(1);
+}
+
+/* ===========================================================================
+ * Compress input to output then close both files.
+ */
+
+void gz_compress(in, out)
+ FILE *in;
+ gzFile out;
+{
+ local char buf[BUFLEN];
+ int len;
+ int err;
+
+#ifdef USE_MMAP
+ /* Try first compressing with mmap. If mmap fails (minigzip used in a
+ * pipe), use the normal fread loop.
+ */
+ if (gz_compress_mmap(in, out) == Z_OK) return;
+#endif
+ for (;;) {
+ len = fread(buf, 1, sizeof(buf), in);
+ if (ferror(in)) {
+ perror("fread");
+ exit(1);
+ }
+ if (len == 0) break;
+
+ if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
+ }
+ fclose(in);
+ if (gzclose(out) != Z_OK) error("failed gzclose");
+}
+
+#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
+
+/* Try compressing the input file at once using mmap. Return Z_OK if
+ * if success, Z_ERRNO otherwise.
+ */
+int gz_compress_mmap(in, out)
+ FILE *in;
+ gzFile out;
+{
+ int len;
+ int err;
+ int ifd = fileno(in);
+ caddr_t buf; /* mmap'ed buffer for the entire input file */
+ off_t buf_len; /* length of the input file */
+ struct stat sb;
+
+ /* Determine the size of the file, needed for mmap: */
+ if (fstat(ifd, &sb) < 0) return Z_ERRNO;
+ buf_len = sb.st_size;
+ if (buf_len <= 0) return Z_ERRNO;
+
+ /* Now do the actual mmap: */
+ buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
+ if (buf == (caddr_t)(-1)) return Z_ERRNO;
+
+ /* Compress the whole file at once: */
+ len = gzwrite(out, (char *)buf, (unsigned)buf_len);
+
+ if (len != (int)buf_len) error(gzerror(out, &err));
+
+ munmap(buf, buf_len);
+ fclose(in);
+ if (gzclose(out) != Z_OK) error("failed gzclose");
+ return Z_OK;
+}
+#endif /* USE_MMAP */
+
+/* ===========================================================================
+ * Uncompress input to output then close both files.
+ */
+void gz_uncompress(in, out)
+ gzFile in;
+ FILE *out;
+{
+ local char buf[BUFLEN];
+ int len;
+ int err;
+
+ for (;;) {
+ len = gzread(in, buf, sizeof(buf));
+ if (len < 0) error (gzerror(in, &err));
+ if (len == 0) break;
+
+ if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
+ error("failed fwrite");
+ }
+ }
+ if (fclose(out)) error("failed fclose");
+
+ if (gzclose(in) != Z_OK) error("failed gzclose");
+}
+
+
+/* ===========================================================================
+ * Compress the given file: create a corresponding .gz file and remove the
+ * original.
+ */
+void file_compress(file, mode)
+ char *file;
+ char *mode;
+{
+ local char outfile[MAX_NAME_LEN];
+ FILE *in;
+ gzFile out;
+
+ strcpy(outfile, file);
+ strcat(outfile, GZ_SUFFIX);
+
+ in = fopen(file, "rb");
+ if (in == NULL) {
+ perror(file);
+ exit(1);
+ }
+ out = gzopen(outfile, mode);
+ if (out == NULL) {
+ fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
+ exit(1);
+ }
+ gz_compress(in, out);
+
+ unlink(file);
+}
+
+
+/* ===========================================================================
+ * Uncompress the given file and remove the original.
+ */
+void file_uncompress(file)
+ char *file;
+{
+ local char buf[MAX_NAME_LEN];
+ char *infile, *outfile;
+ FILE *out;
+ gzFile in;
+ int len = strlen(file);
+
+ strcpy(buf, file);
+
+ if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
+ infile = file;
+ outfile = buf;
+ outfile[len-3] = '\0';
+ } else {
+ outfile = file;
+ infile = buf;
+ strcat(infile, GZ_SUFFIX);
+ }
+ in = gzopen(infile, "rb");
+ if (in == NULL) {
+ fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
+ exit(1);
+ }
+ out = fopen(outfile, "wb");
+ if (out == NULL) {
+ perror(file);
+ exit(1);
+ }
+
+ gz_uncompress(in, out);
+
+ unlink(infile);
+}
+
+
+/* ===========================================================================
+ * Usage: minigzip [-d] [-f] [-h] [-1 to -9] [files...]
+ * -d : decompress
+ * -f : compress with Z_FILTERED
+ * -h : compress with Z_HUFFMAN_ONLY
+ * -1 to -9 : compression level
+ */
+
+int main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int uncompr = 0;
+ gzFile file;
+ char outmode[20];
+
+ strcpy(outmode, "wb6 ");
+
+ prog = argv[0];
+ argc--, argv++;
+
+ while (argc > 0) {
+ if (strcmp(*argv, "-d") == 0)
+ uncompr = 1;
+ else if (strcmp(*argv, "-f") == 0)
+ outmode[3] = 'f';
+ else if (strcmp(*argv, "-h") == 0)
+ outmode[3] = 'h';
+ else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
+ (*argv)[2] == 0)
+ outmode[2] = (*argv)[1];
+ else
+ break;
+ argc--, argv++;
+ }
+ if (argc == 0) {
+ SET_BINARY_MODE(stdin);
+ SET_BINARY_MODE(stdout);
+ if (uncompr) {
+ file = gzdopen(fileno(stdin), "rb");
+ if (file == NULL) error("can't gzdopen stdin");
+ gz_uncompress(file, stdout);
+ } else {
+ file = gzdopen(fileno(stdout), outmode);
+ if (file == NULL) error("can't gzdopen stdout");
+ gz_compress(stdin, file);
+ }
+ } else {
+ do {
+ if (uncompr) {
+ file_uncompress(*argv);
+ } else {
+ file_compress(*argv, outmode);
+ }
+ } while (argv++, --argc);
+ }
+ exit(0);
+ return 0; /* to avoid warning */
+}
diff --git a/cfe/cfe/zlib/trees.c b/cfe/cfe/zlib/trees.c
new file mode 100644
index 0000000..b37335b
--- /dev/null
+++ b/cfe/cfe/zlib/trees.c
@@ -0,0 +1,1214 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-1998 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process uses several Huffman trees. The more
+ * common source values are represented by shorter bit sequences.
+ *
+ * Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values). The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ * Storer, James A.
+ * Data Compression: Methods and Theory, pp. 49-50.
+ * Computer Science Press, 1988. ISBN 0-7167-8156-5.
+ *
+ * Sedgewick, R.
+ * Algorithms, p290.
+ * Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* @(#) $Id: trees.c,v 1.1 2001/11/09 01:48:02 mpl Exp $ */
+
+/* #define GEN_TREES_H */
+
+#include "deflate.h"
+
+#ifdef DEBUG
+# include <ctype.h>
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6 16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10 17
+/* repeat a zero length 3-10 times (3 bits of repeat count) */
+
+#define REPZ_11_138 18
+/* repeat a zero length 11-138 times (7 bits of repeat count) */
+
+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local const int extra_dbits[D_CODES] /* extra bits for each distance code */
+ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local const uch bl_order[BL_CODES]
+ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+#define DIST_CODE_LEN 512 /* see definition of array dist_code below */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+/* non ANSI compilers may not accept trees.h */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+uch _dist_code[DIST_CODE_LEN];
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+uch _length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#else
+# include "trees.h"
+#endif /* GEN_TREES_H */
+
+struct static_tree_desc_s {
+ const ct_data *static_tree; /* static tree or NULL */
+ const intf *extra_bits; /* extra bits for each code or NULL */
+ int extra_base; /* base index for extra_bits */
+ int elems; /* max number of elements in the tree */
+ int max_length; /* max bit length for the codes */
+};
+
+local static_tree_desc static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local static_tree_desc static_d_desc =
+{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
+
+local static_tree_desc static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void tr_static_init OF((void));
+local void init_block OF((deflate_state *s));
+local void pqdownheap OF((deflate_state *s, ct_data *tree, int k));
+local void gen_bitlen OF((deflate_state *s, tree_desc *desc));
+local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count));
+local void build_tree OF((deflate_state *s, tree_desc *desc));
+local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local void send_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local int build_bl_tree OF((deflate_state *s));
+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
+ int blcodes));
+local void compress_block OF((deflate_state *s, ct_data *ltree,
+ ct_data *dtree));
+local void set_data_type OF((deflate_state *s));
+local unsigned bi_reverse OF((unsigned value, int length));
+local void bi_windup OF((deflate_state *s));
+local void bi_flush OF((deflate_state *s));
+local void copy_block OF((deflate_state *s, charf *buf, unsigned len,
+ int header));
+
+#ifdef GEN_TREES_H
+local void gen_trees_header OF((void));
+#endif
+
+#ifndef DEBUG
+# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+ /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+# define send_code(s, c, tree) \
+ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+ send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+ put_byte(s, (uch)((w) & 0xff)); \
+ put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef DEBUG
+local void send_bits OF((deflate_state *s, int value, int length));
+
+local void send_bits(s, value, length)
+ deflate_state *s;
+ int value; /* value to send */
+ int length; /* number of bits */
+{
+ Tracevv((stderr," l %2d v %4x ", length, value));
+ Assert(length > 0 && length <= 15, "invalid length");
+ s->bits_sent += (ulg)length;
+
+ /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+ * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+ * unused bits in value.
+ */
+ if (s->bi_valid > (int)Buf_size - length) {
+ s->bi_buf |= (value << s->bi_valid);
+ put_short(s, s->bi_buf);
+ s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+ s->bi_valid += length - Buf_size;
+ } else {
+ s->bi_buf |= value << s->bi_valid;
+ s->bi_valid += length;
+ }
+}
+#else /* !DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+ if (s->bi_valid > (int)Buf_size - len) {\
+ int val = value;\
+ s->bi_buf |= (val << s->bi_valid);\
+ put_short(s, s->bi_buf);\
+ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+ s->bi_valid += len - Buf_size;\
+ } else {\
+ s->bi_buf |= (value) << s->bi_valid;\
+ s->bi_valid += len;\
+ }\
+}
+#endif /* DEBUG */
+
+
+#define MAX(a,b) (a >= b ? a : b)
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+local void tr_static_init()
+{
+#if defined(GEN_TREES_H) || !defined(STDC)
+ static int static_init_done = 0;
+ int n; /* iterates over tree elements */
+ int bits; /* bit counter */
+ int length; /* length value */
+ int code; /* code value */
+ int dist; /* distance index */
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ if (static_init_done) return;
+
+ /* For some embedded targets, global variables are not initialized: */
+ static_l_desc.static_tree = static_ltree;
+ static_l_desc.extra_bits = extra_lbits;
+ static_d_desc.static_tree = static_dtree;
+ static_d_desc.extra_bits = extra_dbits;
+ static_bl_desc.extra_bits = extra_blbits;
+
+ /* Initialize the mapping length (0..255) -> length code (0..28) */
+ length = 0;
+ for (code = 0; code < LENGTH_CODES-1; code++) {
+ base_length[code] = length;
+ for (n = 0; n < (1<<extra_lbits[code]); n++) {
+ _length_code[length++] = (uch)code;
+ }
+ }
+ Assert (length == 256, "tr_static_init: length != 256");
+ /* Note that the length 255 (match length 258) can be represented
+ * in two different ways: code 284 + 5 bits or code 285, so we
+ * overwrite length_code[255] to use the best encoding:
+ */
+ _length_code[length-1] = (uch)code;
+
+ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+ dist = 0;
+ for (code = 0 ; code < 16; code++) {
+ base_dist[code] = dist;
+ for (n = 0; n < (1<<extra_dbits[code]); n++) {
+ _dist_code[dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: dist != 256");
+ dist >>= 7; /* from now on, all distances are divided by 128 */
+ for ( ; code < D_CODES; code++) {
+ base_dist[code] = dist << 7;
+ for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+ _dist_code[256 + dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+ /* Construct the codes of the static literal tree */
+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+ n = 0;
+ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+ /* Codes 286 and 287 do not exist, but we must include them in the
+ * tree construction to get a canonical Huffman tree (longest code
+ * all ones)
+ */
+ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+ /* The static distance tree is trivial: */
+ for (n = 0; n < D_CODES; n++) {
+ static_dtree[n].Len = 5;
+ static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+ }
+ static_init_done = 1;
+
+# ifdef GEN_TREES_H
+ gen_trees_header();
+# endif
+#endif /* defined(GEN_TREES_H) || !defined(STDC) */
+}
+
+/* ===========================================================================
+ * Genererate the file trees.h describing the static trees.
+ */
+#ifdef GEN_TREES_H
+# ifndef DEBUG
+# include <stdio.h>
+# endif
+
+# define SEPARATOR(i, last, width) \
+ ((i) == (last)? "\n};\n\n" : \
+ ((i) % (width) == (width)-1 ? ",\n" : ", "))
+
+void gen_trees_header()
+{
+ FILE *header = fopen("trees.h", "w");
+ int i;
+
+ Assert (header != NULL, "Can't open trees.h");
+ fprintf(header,
+ "/* header created automatically with -DGEN_TREES_H */\n\n");
+
+ fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
+ for (i = 0; i < L_CODES+2; i++) {
+ fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
+ static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
+ }
+
+ fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+ static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
+ }
+
+ fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n");
+ for (i = 0; i < DIST_CODE_LEN; i++) {
+ fprintf(header, "%2u%s", _dist_code[i],
+ SEPARATOR(i, DIST_CODE_LEN-1, 20));
+ }
+
+ fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+ for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
+ fprintf(header, "%2u%s", _length_code[i],
+ SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
+ }
+
+ fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
+ for (i = 0; i < LENGTH_CODES; i++) {
+ fprintf(header, "%1u%s", base_length[i],
+ SEPARATOR(i, LENGTH_CODES-1, 20));
+ }
+
+ fprintf(header, "local const int base_dist[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "%5u%s", base_dist[i],
+ SEPARATOR(i, D_CODES-1, 10));
+ }
+
+ fclose(header);
+}
+#endif /* GEN_TREES_H */
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void _tr_init(s)
+ deflate_state *s;
+{
+ tr_static_init();
+
+ s->l_desc.dyn_tree = s->dyn_ltree;
+ s->l_desc.stat_desc = &static_l_desc;
+
+ s->d_desc.dyn_tree = s->dyn_dtree;
+ s->d_desc.stat_desc = &static_d_desc;
+
+ s->bl_desc.dyn_tree = s->bl_tree;
+ s->bl_desc.stat_desc = &static_bl_desc;
+
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+#ifdef DEBUG
+ s->compressed_len = 0L;
+ s->bits_sent = 0L;
+#endif
+
+ /* Initialize the first block of the first file: */
+ init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(s)
+ deflate_state *s;
+{
+ int n; /* iterates over tree elements */
+
+ /* Initialize the trees. */
+ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
+ for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
+ for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+ s->dyn_ltree[END_BLOCK].Freq = 1;
+ s->opt_len = s->static_len = 0L;
+ s->last_lit = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+ top = s->heap[SMALLEST]; \
+ s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+ pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+ (tree[n].Freq < tree[m].Freq || \
+ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(s, tree, k)
+ deflate_state *s;
+ ct_data *tree; /* the tree to restore */
+ int k; /* node to move down */
+{
+ int v = s->heap[k];
+ int j = k << 1; /* left son of k */
+ while (j <= s->heap_len) {
+ /* Set j to the smallest of the two sons: */
+ if (j < s->heap_len &&
+ smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+ j++;
+ }
+ /* Exit if v is smaller than both sons */
+ if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+ /* Exchange v with the smallest son */
+ s->heap[k] = s->heap[j]; k = j;
+
+ /* And continue down the tree, setting j to the left son of k */
+ j <<= 1;
+ }
+ s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ * above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ * array bl_count contains the frequencies for each bit length.
+ * The length opt_len is updated; static_len is also updated if stree is
+ * not null.
+ */
+local void gen_bitlen(s, desc)
+ deflate_state *s;
+ tree_desc *desc; /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ int max_code = desc->max_code;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ const intf *extra = desc->stat_desc->extra_bits;
+ int base = desc->stat_desc->extra_base;
+ int max_length = desc->stat_desc->max_length;
+ int h; /* heap index */
+ int n, m; /* iterate over the tree elements */
+ int bits; /* bit length */
+ int xbits; /* extra bits */
+ ush f; /* frequency */
+ int overflow = 0; /* number of elements with bit length too large */
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+ /* In a first pass, compute the optimal bit lengths (which may
+ * overflow in the case of the bit length tree).
+ */
+ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+ for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+ n = s->heap[h];
+ bits = tree[tree[n].Dad].Len + 1;
+ if (bits > max_length) bits = max_length, overflow++;
+ tree[n].Len = (ush)bits;
+ /* We overwrite tree[n].Dad which is no longer needed */
+
+ if (n > max_code) continue; /* not a leaf node */
+
+ s->bl_count[bits]++;
+ xbits = 0;
+ if (n >= base) xbits = extra[n-base];
+ f = tree[n].Freq;
+ s->opt_len += (ulg)f * (bits + xbits);
+ if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
+ }
+ if (overflow == 0) return;
+
+ Trace((stderr,"\nbit length overflow\n"));
+ /* This happens for example on obj2 and pic of the Calgary corpus */
+
+ /* Find the first bit length which could increase: */
+ do {
+ bits = max_length-1;
+ while (s->bl_count[bits] == 0) bits--;
+ s->bl_count[bits]--; /* move one leaf down the tree */
+ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+ s->bl_count[max_length]--;
+ /* The brother of the overflow item also moves one step up,
+ * but this does not affect bl_count[max_length]
+ */
+ overflow -= 2;
+ } while (overflow > 0);
+
+ /* Now recompute all bit lengths, scanning in increasing frequency.
+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+ * lengths instead of fixing only the wrong ones. This idea is taken
+ * from 'ar' written by Haruhiko Okumura.)
+ */
+ for (bits = max_length; bits != 0; bits--) {
+ n = s->bl_count[bits];
+ while (n != 0) {
+ m = s->heap[--h];
+ if (m > max_code) continue;
+ if (tree[m].Len != (unsigned) bits) {
+ Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+ s->opt_len += ((long)bits - (long)tree[m].Len)
+ *(long)tree[m].Freq;
+ tree[m].Len = (ush)bits;
+ }
+ n--;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ * zero code length.
+ */
+local void gen_codes (tree, max_code, bl_count)
+ ct_data *tree; /* the tree to decorate */
+ int max_code; /* largest code with non zero frequency */
+ ushf *bl_count; /* number of codes at each bit length */
+{
+ ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+ ush code = 0; /* running code value */
+ int bits; /* bit index */
+ int n; /* code index */
+
+ /* The distribution counts are first used to generate the code values
+ * without bit reversal.
+ */
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+ }
+ /* Check that the bit counts in bl_count are consistent. The last code
+ * must be all ones.
+ */
+ Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+ "inconsistent bit counts");
+ Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+ for (n = 0; n <= max_code; n++) {
+ int len = tree[n].Len;
+ if (len == 0) continue;
+ /* Now reverse the bits */
+ tree[n].Code = bi_reverse(next_code[len]++, len);
+
+ Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+ n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+ }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ * and corresponding code. The length opt_len is updated; static_len is
+ * also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(s, desc)
+ deflate_state *s;
+ tree_desc *desc; /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ int elems = desc->stat_desc->elems;
+ int n, m; /* iterate over heap elements */
+ int max_code = -1; /* largest code with non zero frequency */
+ int node; /* new node being created */
+
+ /* Construct the initial heap, with least frequent element in
+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ * heap[0] is not used.
+ */
+ s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++) {
+ if (tree[n].Freq != 0) {
+ s->heap[++(s->heap_len)] = max_code = n;
+ s->depth[n] = 0;
+ } else {
+ tree[n].Len = 0;
+ }
+ }
+
+ /* The pkzip format requires that at least one distance code exists,
+ * and that at least one bit should be sent even if there is only one
+ * possible code. So to avoid special checks later on we force at least
+ * two codes of non zero frequency.
+ */
+ while (s->heap_len < 2) {
+ node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+ tree[node].Freq = 1;
+ s->depth[node] = 0;
+ s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+ /* node is 0 or 1 so it does not have extra bits */
+ }
+ desc->max_code = max_code;
+
+ /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ * establish sub-heaps of increasing lengths:
+ */
+ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+ /* Construct the Huffman tree by repeatedly combining the least two
+ * frequent nodes.
+ */
+ node = elems; /* next internal node of the tree */
+ do {
+ pqremove(s, tree, n); /* n = node of least frequency */
+ m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+ s->heap[--(s->heap_max)] = m;
+
+ /* Create a new node father of n and m */
+ tree[node].Freq = tree[n].Freq + tree[m].Freq;
+ s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1);
+ tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+ if (tree == s->bl_tree) {
+ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+ }
+#endif
+ /* and insert the new node in the heap */
+ s->heap[SMALLEST] = node++;
+ pqdownheap(s, tree, SMALLEST);
+
+ } while (s->heap_len >= 2);
+
+ s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+ /* At this point, the fields freq and dad are set. We can now
+ * generate the bit lengths.
+ */
+ gen_bitlen(s, (tree_desc *)desc);
+
+ /* The field len is now set, we can generate the bit codes */
+ gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree (s, tree, max_code)
+ deflate_state *s;
+ ct_data *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ if (nextlen == 0) max_count = 138, min_count = 3;
+ tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ s->bl_tree[curlen].Freq += count;
+ } else if (curlen != 0) {
+ if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+ s->bl_tree[REP_3_6].Freq++;
+ } else if (count <= 10) {
+ s->bl_tree[REPZ_3_10].Freq++;
+ } else {
+ s->bl_tree[REPZ_11_138].Freq++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (s, tree, max_code)
+ deflate_state *s;
+ ct_data *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ /* tree[max_code+1].Len = -1; */ /* guard already set */
+ if (nextlen == 0) max_count = 138, min_count = 3;
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+ } else if (curlen != 0) {
+ if (curlen != prevlen) {
+ send_code(s, curlen, s->bl_tree); count--;
+ }
+ Assert(count >= 3 && count <= 6, " 3_6?");
+ send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+
+ } else if (count <= 10) {
+ send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+
+ } else {
+ send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(s)
+ deflate_state *s;
+{
+ int max_blindex; /* index of last bit length code of non zero freq */
+
+ /* Determine the bit length frequencies for literal and distance trees */
+ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+ scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+ /* Build the bit length tree: */
+ build_tree(s, (tree_desc *)(&(s->bl_desc)));
+ /* opt_len now includes the length of the tree representations, except
+ * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+ */
+
+ /* Determine the number of bit length codes to send. The pkzip format
+ * requires that at least 4 bit length codes be sent. (appnote.txt says
+ * 3 but the actual value used is 4.)
+ */
+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+ if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+ }
+ /* Update opt_len to include the bit length tree and counts */
+ s->opt_len += 3*(max_blindex+1) + 5+5+4;
+ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+ s->opt_len, s->static_len));
+
+ return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(s, lcodes, dcodes, blcodes)
+ deflate_state *s;
+ int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+ int rank; /* index in bl_order */
+
+ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+ "too many codes");
+ Tracev((stderr, "\nbl counts: "));
+ send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+ send_bits(s, dcodes-1, 5);
+ send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */
+ for (rank = 0; rank < blcodes; rank++) {
+ Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+ send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+ }
+ Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void _tr_stored_block(s, buf, stored_len, eof)
+ deflate_state *s;
+ charf *buf; /* input block */
+ ulg stored_len; /* length of input block */
+ int eof; /* true if this is the last block for a file */
+{
+ send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */
+#ifdef DEBUG
+ s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+ s->compressed_len += (stored_len + 4) << 3;
+#endif
+ copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ * The current inflate code requires 9 bits of lookahead. If the
+ * last two codes for the previous block (real code plus EOB) were coded
+ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ * the last real code. In this case we send two empty static blocks instead
+ * of one. (There are no problems if the previous block is stored or fixed.)
+ * To simplify the code, we assume the worst case of last real code encoded
+ * on one bit only.
+ */
+void _tr_align(s)
+ deflate_state *s;
+{
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+ s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+#endif
+ bi_flush(s);
+ /* Of the 10 bits for the empty block, we have already sent
+ * (10 - bi_valid) bits. The lookahead for the last real code (before
+ * the EOB of the previous block) was thus at least one plus the length
+ * of the EOB plus what we have just sent of the empty static block.
+ */
+ if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+ s->compressed_len += 10L;
+#endif
+ bi_flush(s);
+ }
+ s->last_eob_len = 7;
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file.
+ */
+void _tr_flush_block(s, buf, stored_len, eof)
+ deflate_state *s;
+ charf *buf; /* input block, or NULL if too old */
+ ulg stored_len; /* length of input block */
+ int eof; /* true if this is the last block for a file */
+{
+ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+ int max_blindex = 0; /* index of last bit length code of non zero freq */
+
+ /* Build the Huffman trees unless a stored block is forced */
+ if (s->level > 0) {
+
+ /* Check if the file is ascii or binary */
+ if (s->data_type == Z_UNKNOWN) set_data_type(s);
+
+ /* Construct the literal and distance trees */
+ build_tree(s, (tree_desc *)(&(s->l_desc)));
+ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+
+ build_tree(s, (tree_desc *)(&(s->d_desc)));
+ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+ /* At this point, opt_len and static_len are the total bit lengths of
+ * the compressed block data, excluding the tree representations.
+ */
+
+ /* Build the bit length tree for the above two trees, and get the index
+ * in bl_order of the last bit length code to send.
+ */
+ max_blindex = build_bl_tree(s);
+
+ /* Determine the best encoding. Compute first the block length in bytes*/
+ opt_lenb = (s->opt_len+3+7)>>3;
+ static_lenb = (s->static_len+3+7)>>3;
+
+ Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+ opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+ s->last_lit));
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+ } else {
+ Assert(buf != (char*)0, "lost buf");
+ opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+ }
+
+#ifdef FORCE_STORED
+ if (buf != (char*)0) { /* force stored block */
+#else
+ if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+ /* 4: two words for the lengths */
+#endif
+ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ * Otherwise we can't have processed more than WSIZE input bytes since
+ * the last block flush, because compression would have been
+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ * transform a block into a stored block.
+ */
+ _tr_stored_block(s, buf, stored_len, eof);
+
+#ifdef FORCE_STATIC
+ } else if (static_lenb >= 0) { /* force static trees */
+#else
+ } else if (static_lenb == opt_lenb) {
+#endif
+ send_bits(s, (STATIC_TREES<<1)+eof, 3);
+ compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+#ifdef DEBUG
+ s->compressed_len += 3 + s->static_len;
+#endif
+ } else {
+ send_bits(s, (DYN_TREES<<1)+eof, 3);
+ send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
+ max_blindex+1);
+ compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+#ifdef DEBUG
+ s->compressed_len += 3 + s->opt_len;
+#endif
+ }
+ Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+ /* The above check is made mod 2^32, for files larger than 512 MB
+ * and uLong implemented on 32 bits.
+ */
+ init_block(s);
+
+ if (eof) {
+ bi_windup(s);
+#ifdef DEBUG
+ s->compressed_len += 7; /* align on byte boundary */
+#endif
+ }
+ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+ s->compressed_len-7*eof));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int _tr_tally (s, dist, lc)
+ deflate_state *s;
+ unsigned dist; /* distance of matched string */
+ unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+ s->d_buf[s->last_lit] = (ush)dist;
+ s->l_buf[s->last_lit++] = (uch)lc;
+ if (dist == 0) {
+ /* lc is the unmatched char */
+ s->dyn_ltree[lc].Freq++;
+ } else {
+ s->matches++;
+ /* Here, lc is the match length - MIN_MATCH */
+ dist--; /* dist = match distance - 1 */
+ Assert((ush)dist < (ush)MAX_DIST(s) &&
+ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+ (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
+
+ s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
+ s->dyn_dtree[d_code(dist)].Freq++;
+ }
+
+#ifdef TRUNCATE_BLOCK
+ /* Try to guess if it is profitable to stop the current block here */
+ if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
+ /* Compute an upper bound for the compressed length */
+ ulg out_length = (ulg)s->last_lit*8L;
+ ulg in_length = (ulg)((long)s->strstart - s->block_start);
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++) {
+ out_length += (ulg)s->dyn_dtree[dcode].Freq *
+ (5L+extra_dbits[dcode]);
+ }
+ out_length >>= 3;
+ Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+ s->last_lit, in_length, out_length,
+ 100L - out_length*100L/in_length));
+ if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
+ }
+#endif
+ return (s->last_lit == s->lit_bufsize-1);
+ /* We avoid equality with lit_bufsize because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(s, ltree, dtree)
+ deflate_state *s;
+ ct_data *ltree; /* literal tree */
+ ct_data *dtree; /* distance tree */
+{
+ unsigned dist; /* distance of matched string */
+ int lc; /* match length or unmatched char (if dist == 0) */
+ unsigned lx = 0; /* running index in l_buf */
+ unsigned code; /* the code to send */
+ int extra; /* number of extra bits to send */
+
+ if (s->last_lit != 0) do {
+ dist = s->d_buf[lx];
+ lc = s->l_buf[lx++];
+ if (dist == 0) {
+ send_code(s, lc, ltree); /* send a literal byte */
+ Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ code = _length_code[lc];
+ send_code(s, code+LITERALS+1, ltree); /* send the length code */
+ extra = extra_lbits[code];
+ if (extra != 0) {
+ lc -= base_length[code];
+ send_bits(s, lc, extra); /* send the extra length bits */
+ }
+ dist--; /* dist is now the match distance - 1 */
+ code = d_code(dist);
+ Assert (code < D_CODES, "bad d_code");
+
+ send_code(s, code, dtree); /* send the distance code */
+ extra = extra_dbits[code];
+ if (extra != 0) {
+ dist -= base_dist[code];
+ send_bits(s, dist, extra); /* send the extra distance bits */
+ }
+ } /* literal or match pair ? */
+
+ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+ Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow");
+
+ } while (lx < s->last_lit);
+
+ send_code(s, END_BLOCK, ltree);
+ s->last_eob_len = ltree[END_BLOCK].Len;
+}
+
+/* ===========================================================================
+ * Set the data type to ASCII or BINARY, using a crude approximation:
+ * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ * IN assertion: the fields freq of dyn_ltree are set and the total of all
+ * frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ */
+local void set_data_type(s)
+ deflate_state *s;
+{
+ int n = 0;
+ unsigned ascii_freq = 0;
+ unsigned bin_freq = 0;
+ while (n < 7) bin_freq += s->dyn_ltree[n++].Freq;
+ while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq;
+ while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq;
+ s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII);
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(code, len)
+ unsigned code; /* the value to invert */
+ int len; /* its bit length */
+{
+ register unsigned res = 0;
+ do {
+ res |= code & 1;
+ code >>= 1, res <<= 1;
+ } while (--len > 0);
+ return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(s)
+ deflate_state *s;
+{
+ if (s->bi_valid == 16) {
+ put_short(s, s->bi_buf);
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ } else if (s->bi_valid >= 8) {
+ put_byte(s, (Byte)s->bi_buf);
+ s->bi_buf >>= 8;
+ s->bi_valid -= 8;
+ }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(s)
+ deflate_state *s;
+{
+ if (s->bi_valid > 8) {
+ put_short(s, s->bi_buf);
+ } else if (s->bi_valid > 0) {
+ put_byte(s, (Byte)s->bi_buf);
+ }
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+#ifdef DEBUG
+ s->bits_sent = (s->bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+local void copy_block(s, buf, len, header)
+ deflate_state *s;
+ charf *buf; /* the input data */
+ unsigned len; /* its length */
+ int header; /* true if block header must be written */
+{
+ bi_windup(s); /* align on byte boundary */
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+
+ if (header) {
+ put_short(s, (ush)len);
+ put_short(s, (ush)~len);
+#ifdef DEBUG
+ s->bits_sent += 2*16;
+#endif
+ }
+#ifdef DEBUG
+ s->bits_sent += (ulg)len<<3;
+#endif
+ while (len--) {
+ put_byte(s, *buf++);
+ }
+}
diff --git a/cfe/cfe/zlib/trees.h b/cfe/cfe/zlib/trees.h
new file mode 100644
index 0000000..72facf9
--- /dev/null
+++ b/cfe/cfe/zlib/trees.h
@@ -0,0 +1,128 @@
+/* header created automatically with -DGEN_TREES_H */
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
+{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
+{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
+{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
+{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
+{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
+{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
+{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
+{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
+{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
+{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
+{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
+{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
+{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
+{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
+{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
+{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
+{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
+{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
+{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
+{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
+{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
+{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
+{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
+{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
+{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
+{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
+{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
+{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
+{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
+{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
+{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
+{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
+{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
+{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
+{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
+{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
+{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
+{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
+{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
+{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
+{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
+{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
+{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
+{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
+{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
+{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
+{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
+{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
+{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
+{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
+{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
+{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
+{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
+{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
+{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
+{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
+{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch _dist_code[DIST_CODE_LEN] = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+};
+
diff --git a/cfe/cfe/zlib/uncompr.c b/cfe/cfe/zlib/uncompr.c
new file mode 100644
index 0000000..eab3f5b
--- /dev/null
+++ b/cfe/cfe/zlib/uncompr.c
@@ -0,0 +1,58 @@
+/* uncompr.c -- decompress a memory buffer
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: uncompr.c,v 1.1 2001/11/09 01:48:02 mpl Exp $ */
+
+#include "zlib.h"
+
+/* ===========================================================================
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+int ZEXPORT uncompress (dest, destLen, source, sourceLen)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+
+ err = inflateInit(&stream);
+ if (err != Z_OK) return err;
+
+ err = inflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ inflateEnd(&stream);
+ return err == Z_OK ? Z_BUF_ERROR : err;
+ }
+ *destLen = stream.total_out;
+
+ err = inflateEnd(&stream);
+ return err;
+}
diff --git a/cfe/cfe/zlib/zconf.h b/cfe/cfe/zlib/zconf.h
new file mode 100644
index 0000000..23a52b3
--- /dev/null
+++ b/cfe/cfe/zlib/zconf.h
@@ -0,0 +1,279 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: zconf.h,v 1.1 2001/11/09 01:48:02 mpl Exp $ */
+
+#ifndef _ZCONF_H
+#define _ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+# define deflateInit_ z_deflateInit_
+# define deflate z_deflate
+# define deflateEnd z_deflateEnd
+# define inflateInit_ z_inflateInit_
+# define inflate z_inflate
+# define inflateEnd z_inflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateCopy z_deflateCopy
+# define deflateReset z_deflateReset
+# define deflateParams z_deflateParams
+# define inflateInit2_ z_inflateInit2_
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateReset z_inflateReset
+# define compress z_compress
+# define compress2 z_compress2
+# define uncompress z_uncompress
+# define adler32 z_adler32
+# define crc32 z_crc32
+# define get_crc_table z_get_crc_table
+
+# define Byte z_Byte
+# define uInt z_uInt
+# define uLong z_uLong
+# define Bytef z_Bytef
+# define charf z_charf
+# define intf z_intf
+# define uIntf z_uIntf
+# define uLongf z_uLongf
+# define voidpf z_voidpf
+# define voidp z_voidp
+#endif
+
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+# define WIN32
+#endif
+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
+# ifndef __32BIT__
+# define __32BIT__
+# endif
+#endif
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#if defined(MSDOS) && !defined(__32BIT__)
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC)
+# define STDC
+#endif
+#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__)
+# ifndef STDC
+# define STDC
+# endif
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Old Borland C incorrectly complains about missing returns: */
+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
+# define NEED_DUMMY_RETURN
+#endif
+
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# if defined(STDC) || defined(_CFE_)
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+#endif
+#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
+# ifndef __32BIT__
+# define SMALL_MEDIUM
+# define FAR _far
+# endif
+#endif
+
+/* Compile with -DZLIB_DLL for Windows DLL support */
+#if defined(ZLIB_DLL)
+# if defined(_WINDOWS) || defined(WINDOWS)
+# ifdef FAR
+# undef FAR
+# endif
+# include <windows.h>
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR _cdecl _export
+# endif
+# endif
+# if defined (__BORLANDC__)
+# if (__BORLANDC__ >= 0x0500) && defined (WIN32)
+# include <windows.h>
+# define ZEXPORT __declspec(dllexport) WINAPI
+# define ZEXPORTRVA __declspec(dllexport) WINAPIV
+# else
+# if defined (_Windows) && defined (__DLL__)
+# define ZEXPORT _export
+# define ZEXPORTVA _export
+# endif
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# if defined (ZLIB_DLL)
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+#endif
+
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(MACOS) && !defined(TARGET_OS_MAC)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <sys/types.h> /* for off_t */
+# include <unistd.h> /* for SEEK_* and off_t */
+# define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+# pragma map(deflateInit_,"DEIN")
+# pragma map(deflateInit2_,"DEIN2")
+# pragma map(deflateEnd,"DEEND")
+# pragma map(inflateInit_,"ININ")
+# pragma map(inflateInit2_,"ININ2")
+# pragma map(inflateEnd,"INEND")
+# pragma map(inflateSync,"INSY")
+# pragma map(inflateSetDictionary,"INSEDI")
+# pragma map(inflate_blocks,"INBL")
+# pragma map(inflate_blocks_new,"INBLNE")
+# pragma map(inflate_blocks_free,"INBLFR")
+# pragma map(inflate_blocks_reset,"INBLRE")
+# pragma map(inflate_codes_free,"INCOFR")
+# pragma map(inflate_codes,"INCO")
+# pragma map(inflate_fast,"INFA")
+# pragma map(inflate_flush,"INFLU")
+# pragma map(inflate_mask,"INMA")
+# pragma map(inflate_set_dictionary,"INSEDI2")
+# pragma map(inflate_copyright,"INCOPY")
+# pragma map(inflate_trees_bits,"INTRBI")
+# pragma map(inflate_trees_dynamic,"INTRDY")
+# pragma map(inflate_trees_fixed,"INTRFI")
+# pragma map(inflate_trees_free,"INTRFR")
+#endif
+
+#endif /* _ZCONF_H */
diff --git a/cfe/cfe/zlib/zlib.3 b/cfe/cfe/zlib/zlib.3
new file mode 100644
index 0000000..25c8495
--- /dev/null
+++ b/cfe/cfe/zlib/zlib.3
@@ -0,0 +1,107 @@
+.TH ZLIB 3 "9 July 1998"
+.SH NAME
+zlib \- compression/decompression library
+.SH SYNOPSIS
+[see
+.I zlib.h
+for full description]
+.SH DESCRIPTION
+The
+.I zlib
+library is a general purpose data compression library.
+The code is thread safe.
+It provides in-memory compression and decompression functions,
+including integrity checks of the uncompressed data.
+This version of the library supports only one compression method (deflation)
+but other algorithms will be added later and will have the same stream interface.
+.LP
+Compression can be done in a single step if the buffers are large enough
+(for example if an input file is mmap'ed),
+or can be done by repeated calls of the compression function.
+In the latter case,
+the application must provide more input and/or consume the output
+(providing more output space) before each call.
+.LP
+The library also supports reading and writing files in
+.I gzip
+(.gz) format
+with an interface similar to that of stdio.
+.LP
+The library does not install any signal handler. The decoder checks
+the consistency of the compressed data, so the library should never
+crash even in case of corrupted input.
+.LP
+All functions of the compression library are documented in the file
+.IR zlib.h.
+The distribution source includes examples of use of the library
+the files
+.I example.c
+and
+.IR minigzip.c .
+.LP
+A Java implementation of
+.IR zlib
+is available in the Java Development Kit 1.1
+.IP
+http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html
+.LP
+A Perl interface to
+.IR zlib ,
+written by Paul Marquess (pmarquess@bfsec.bt.co.uk)
+is available at CPAN (Comprehensive Perl Archive Network) sites,
+such as:
+.IP
+ftp://ftp.cis.ufl.edu/pub/perl/CPAN/modules/by-module/Compress/Compress-Zlib*
+.LP
+A Python interface to
+.IR zlib
+written by A.M. Kuchling <amk@magnet.com>
+is available from the Python Software Association sites, such as:
+.IP
+ftp://ftp.python.org/pub/python/contrib/Encoding/zlib*.tar.gz
+.SH "SEE ALSO"
+Questions about zlib should be sent to:
+.IP
+zlib@quest.jpl.nasa.gov
+or, if this fails, to the author addresses given below.
+The zlib home page is:
+.IP
+http://www.cdrom.com/pub/infozip/zlib/
+.LP
+The data format used by the zlib library is described by RFC
+(Request for Comments) 1950 to 1952 in the files:
+.IP
+ftp://ds.internic.net/rfc/rfc1950.txt (zlib format)
+.br
+rfc1951.txt (deflate format)
+.br
+rfc1952.txt (gzip format)
+.LP
+These documents are also available in other formats from:
+.IP
+ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
+.SH AUTHORS
+Version 1.1.3
+Copyright (C) 1995-1998 Jean-loup Gailly (jloup@gzip.org)
+and Mark Adler (madler@alumni.caltech.edu).
+.LP
+This software is provided "as-is,"
+without any express or implied warranty.
+In no event will the authors be held liable for any damages
+arising from the use of this software.
+See the distribution directory with respect to requirements
+governing redistribution.
+The deflate format used by
+.I zlib
+was defined by Phil Katz.
+The deflate and
+.I zlib
+specifications were written by L. Peter Deutsch.
+Thanks to all the people who reported problems and suggested various
+improvements in
+.IR zlib ;
+who are too numerous to cite here.
+.LP
+UNIX manual page by R. P. C. Rodgers,
+U.S. National Library of Medicine (rodgers@nlm.nih.gov).
+.\" end of man page
diff --git a/cfe/cfe/zlib/zlib.h b/cfe/cfe/zlib/zlib.h
new file mode 100644
index 0000000..49f56b4
--- /dev/null
+++ b/cfe/cfe/zlib/zlib.h
@@ -0,0 +1,893 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.1.3, July 9th, 1998
+
+ Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.1.3"
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms will be added later and will have the same
+ stream interface.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never
+ crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: ascii or binary */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe.
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+/* Allowed flush values; see deflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_ASCII 1
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+ /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller.
+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+ use default allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at
+ all (the input data is simply copied a block at a time).
+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+ compression (currently equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION).
+ msg is set to null if there is no error message. deflateInit does not
+ perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce some
+ output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications).
+ Some output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating avail_in or avail_out accordingly; avail_out
+ should never be zero before the call. The application can consume the
+ compressed output when it wants, for example when the output buffer is full
+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+ and with zero avail_out, it must be called again after making room in the
+ output buffer because there might be more output pending.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In particular
+ avail_in is zero after the call if enough output space has been provided
+ before the call.) Flushing may degrade compression for some compression
+ algorithms and so it should be used only when necessary.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ the compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out).
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there
+ was enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the
+ stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least
+ 0.1% larger than avail_in plus 12 bytes. If deflate does not return
+ Z_STREAM_END, then it must be called again as described above.
+
+ deflate() sets strm->adler to the adler32 checksum of all input read
+ so far (that is, total_in bytes).
+
+ deflate() may update data_type if it can make a good guess about
+ the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect
+ the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+ (for example avail_in or avail_out was zero).
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case,
+ msg may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+ value depends on the compression method), inflateInit determines the
+ compression method from the zlib header and allocates all data structures
+ accordingly; otherwise the allocation will be deferred to the first call of
+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+ use default allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller. msg is set to null if there is no error
+ message. inflateInit does not perform any decompression apart from reading
+ the zlib header if present: this will be done by inflate(). (So next_in and
+ avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may some
+ introduce some output latency (reading input without producing any output)
+ except when forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there
+ is no more input data or no more space in the output buffer (see below
+ about the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+ must be called again after making room in the output buffer because there
+ might be more output pending.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
+ output as possible to the output buffer. The flushing behavior of inflate is
+ not specified for values of the flush parameter other than Z_SYNC_FLUSH
+ and Z_FINISH, but the current implementation actually flushes as much output
+ as possible anyway.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster routine
+ may be used for the single inflate() call.
+
+ If a preset dictionary is needed at this point (see inflateSetDictionary
+ below), inflate sets strm-adler to the adler32 checksum of the
+ dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise
+ it sets strm->adler to the adler32 checksum of all output produced
+ so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
+ an error code as described below. At the end of the stream, inflate()
+ checks that its computed adler32 checksum is equal to that saved by the
+ compressor and returns Z_STREAM_END only if the checksum is correct.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect
+ adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
+ (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if no progress is possible or if there was not
+ enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
+ case, the application may then call inflateSync to look for a good
+ compression block.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but
+ is slow and reduces compression ratio; memLevel=9 uses maximum memory
+ for optimal speed. The default value is 8. See zconf.h for total memory
+ usage as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match). Filtered data consists mostly of small values with a
+ somewhat random distribution. In this case, the compression algorithm is
+ tuned to compress them better. The effect of Z_FILTERED is to force more
+ Huffman coding and less string matching; it is somewhat intermediate
+ between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
+ the compression ratio but not the correctness of the compressed output even
+ if it is not set appropriately.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+ method). msg is set to null if there is no error message. deflateInit2 does
+ not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. This function must be called
+ immediately after deflateInit, deflateInit2 or deflateReset, before any
+ call of deflate. The compressor and decompressor must use exactly the same
+ dictionary (see inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size in
+ deflate or deflate2. Thus the strings most likely to be useful should be
+ put at the end of the dictionary, not at the front.
+
+ Upon return of this function, strm->adler is set to the Adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The Adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.)
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if the compression method is bsort). deflateSetDictionary does not
+ perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and
+ can consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state.
+ The stream will keep the same compression level and any other attributes
+ that may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+ int level,
+ int strategy));
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2. This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different
+ strategy. If the compression level is changed, the input available so far
+ is compressed with the old level (and may be flushed); the new level will
+ take effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to
+ be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+ if strm->avail_out was zero.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. If a compressed stream with a larger window size is given as
+ input, inflate() will return with the error code Z_DATA_ERROR instead of
+ trying to allocate a larger window.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
+ memLevel). msg is set to null if there is no error message. inflateInit2
+ does not perform any decompression apart from reading the zlib header if
+ present: this will be done by inflate(). (So next_in and avail_in may be
+ modified, but next_out and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate
+ if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the Adler32 value returned by this call of
+ inflate. The compressor and decompressor must use exactly the same
+ dictionary (see deflateSetDictionary).
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect Adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+ Skips invalid compressed data until a full flush point (see above the
+ description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the
+ basic stream-oriented functions. To simplify the interface, some
+ default options are assumed (compression level and memory usage,
+ standard memory allocation functions). The source code of these
+ utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least 0.1% larger than
+ sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level));
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least 0.1% larger than sourceLen plus
+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+/*
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb") but can also include a compression level
+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+ Huffman only compression as in "wb1h". (See the description
+ of deflateInit2 for more information about the strategy parameter.)
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression.
+
+ gzopen returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR). */
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+ gzdopen() associates a gzFile with the file descriptor fd. File
+ descriptors are obtained from calls like open, dup, creat, pipe or
+ fileno (in the file has been previously opened with fopen).
+ The mode parameter is as in gzopen.
+ The next call of gzclose on the returned gzFile will also close the
+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+ gzdopen returns NULL if there was insufficient memory to allocate
+ the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+ Dynamically update the compression level or strategy. See the description
+ of deflateInit2 for the meaning of these parameters.
+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+ opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+ Reads the given number of uncompressed bytes from the compressed file.
+ If the input file was not in gzip format, gzread copies the given number
+ of bytes into the buffer.
+ gzread returns the number of uncompressed bytes actually read (0 for
+ end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+ const voidp buf, unsigned len));
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes actually written
+ (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
+/*
+ Converts, formats, and writes the args to the compressed file under
+ control of the format string, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+ Writes the given null-terminated string to the compressed file, excluding
+ the terminating null character.
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+ Reads bytes from the compressed file until len-1 characters are read, or
+ a newline character is read and transferred to buf, or an end-of-file
+ condition is encountered. The string is then terminated with a null
+ character.
+ gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+ Writes c, converted to an unsigned char, into the compressed file.
+ gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+ Reads one byte from the compressed file. gzgetc returns this byte
+ or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function. The return value is the zlib
+ error number (see function gzerror below). gzflush returns Z_OK if
+ the flush parameter is Z_FINISH and all output could be flushed.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+ z_off_t offset, int whence));
+/*
+ Sets the starting position for the next gzread or gzwrite on the
+ given compressed file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
+/*
+ Rewinds the given file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
+/*
+ Returns the starting position for the next gzread or gzwrite on the
+ given compressed file. This position represents a number of bytes in the
+ uncompressed data stream.
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+ Returns 1 when EOF has previously been detected reading the given
+ input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT gzclose OF((gzFile file));
+/*
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state. The return value is the zlib
+ error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+ Returns the error message for the last error which occurred on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occurred in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the
+ compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULL, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+/*
+ Update a running crc with the bytes buf[0..len-1] and return the updated
+ crc. If buf is NULL, this function returns the required initial value
+ for the crc. Pre- and post-conditioning (one's complement) is performed
+ within this function so it shouldn't be done by the application.
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
+ struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char * ZEXPORT zError OF((int err));
+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZLIB_H */
diff --git a/cfe/cfe/zlib/zutil.c b/cfe/cfe/zlib/zutil.c
new file mode 100644
index 0000000..52a8197
--- /dev/null
+++ b/cfe/cfe/zlib/zutil.c
@@ -0,0 +1,225 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: zutil.c,v 1.1 2001/11/09 01:48:02 mpl Exp $ */
+
+#include "zutil.h"
+
+struct internal_state {int dummy;}; /* for buggy compilers */
+
+#ifndef STDC
+extern void exit OF((int));
+#endif
+
+const char *z_errmsg[10] = {
+"need dictionary", /* Z_NEED_DICT 2 */
+"stream end", /* Z_STREAM_END 1 */
+"", /* Z_OK 0 */
+"file error", /* Z_ERRNO (-1) */
+"stream error", /* Z_STREAM_ERROR (-2) */
+"data error", /* Z_DATA_ERROR (-3) */
+"insufficient memory", /* Z_MEM_ERROR (-4) */
+"buffer error", /* Z_BUF_ERROR (-5) */
+"incompatible version",/* Z_VERSION_ERROR (-6) */
+""};
+
+
+const char * ZEXPORT zlibVersion()
+{
+ return ZLIB_VERSION;
+}
+
+#ifdef DEBUG
+
+# ifndef verbose
+# define verbose 0
+# endif
+int z_verbose = verbose;
+
+void z_error (m)
+ char *m;
+{
+ fprintf(stderr, "%s\n", m);
+ exit(1);
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(err)
+ int err;
+{
+ return ERR_MSG(err);
+}
+
+
+#ifndef HAVE_MEMCPY
+
+void zmemcpy(dest, source, len)
+ Bytef* dest;
+ const Bytef* source;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = *source++; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+
+int zmemcmp(s1, s2, len)
+ const Bytef* s1;
+ const Bytef* s2;
+ uInt len;
+{
+ uInt j;
+
+ for (j = 0; j < len; j++) {
+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+ }
+ return 0;
+}
+
+void zmemzero(dest, len)
+ Bytef* dest;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = 0; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+#endif
+
+#ifdef __TURBOC__
+#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__)
+/* Small and medium model in Turbo C are for now limited to near allocation
+ * with reduced MAX_WBITS and MAX_MEM_LEVEL
+ */
+# define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+ voidpf org_ptr;
+ voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ voidpf buf = opaque; /* just to make some compilers happy */
+ ulg bsize = (ulg)items*size;
+
+ /* If we allocate less than 65520 bytes, we assume that farmalloc
+ * will return a usable pointer which doesn't have to be normalized.
+ */
+ if (bsize < 65520L) {
+ buf = farmalloc(bsize);
+ if (*(ush*)&buf != 0) return buf;
+ } else {
+ buf = farmalloc(bsize + 16L);
+ }
+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+ table[next_ptr].org_ptr = buf;
+
+ /* Normalize the pointer to seg:0 */
+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+ *(ush*)&buf = 0;
+ table[next_ptr++].new_ptr = buf;
+ return buf;
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ int n;
+ if (*(ush*)&ptr != 0) { /* object < 64K */
+ farfree(ptr);
+ return;
+ }
+ /* Find the original pointer */
+ for (n = 0; n < next_ptr; n++) {
+ if (ptr != table[n].new_ptr) continue;
+
+ farfree(table[n].org_ptr);
+ while (++n < next_ptr) {
+ table[n-1] = table[n];
+ }
+ next_ptr--;
+ return;
+ }
+ ptr = opaque; /* just to make some compilers happy */
+ Assert(0, "zcfree: ptr not found");
+}
+#endif
+#endif /* __TURBOC__ */
+
+
+#if defined(M_I86) && !defined(__32BIT__)
+/* Microsoft C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+# define _halloc halloc
+# define _hfree hfree
+#endif
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ return _halloc((long)items, size);
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ _hfree(ptr);
+}
+
+#endif /* MSC */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp calloc OF((uInt items, uInt size));
+extern void free OF((voidpf ptr));
+#endif
+
+voidpf zcalloc (opaque, items, size)
+ voidpf opaque;
+ unsigned items;
+ unsigned size;
+{
+ if (opaque) items += size - size; /* make compiler happy */
+ return (voidpf)calloc(items, size);
+}
+
+void zcfree (opaque, ptr)
+ voidpf opaque;
+ voidpf ptr;
+{
+ free(ptr);
+ if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
diff --git a/cfe/cfe/zlib/zutil.h b/cfe/cfe/zlib/zutil.h
new file mode 100644
index 0000000..6dc18e1
--- /dev/null
+++ b/cfe/cfe/zlib/zutil.h
@@ -0,0 +1,220 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id: zutil.h,v 1.1 2001/11/09 01:48:02 mpl Exp $ */
+
+#ifndef _Z_UTIL_H
+#define _Z_UTIL_H
+
+#include "zlib.h"
+
+#ifdef STDC
+# include <stddef.h>
+# include <string.h>
+# include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+ extern int errno;
+#else
+# include <errno.h>
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+ return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+ /* target dependencies */
+
+#ifdef MSDOS
+# define OS_CODE 0x00
+# if defined(__TURBOC__) || defined(__BORLANDC__)
+# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+ /* Allow compilation with ANSI keywords only enabled */
+ void _Cdecl farfree( void *block );
+ void *_Cdecl farmalloc( unsigned long nbytes );
+# else
+# include <alloc.h>
+# endif
+# else /* MSC or DJGPP */
+# include <malloc.h>
+# endif
+#endif
+
+#ifdef OS2
+# define OS_CODE 0x06
+#endif
+
+#ifdef WIN32 /* Window 95 & Windows NT */
+# define OS_CODE 0x0b
+#endif
+
+#if defined(VAXC) || defined(VMS)
+# define OS_CODE 0x02
+# define F_OPEN(name, mode) \
+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#ifdef AMIGA
+# define OS_CODE 0x01
+#endif
+
+#if defined(ATARI) || defined(atarist)
+# define OS_CODE 0x05
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+# define OS_CODE 0x07
+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+# include <unix.h> /* for fdopen */
+# else
+# ifndef fdopen
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# endif
+# endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+# define OS_CODE 0x0F
+#endif
+
+#ifdef TOPS20
+# define OS_CODE 0x0a
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600))
+# define fdopen(fd,type) _fdopen(fd,type)
+#endif
+
+
+ /* Common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+# define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+ /* functions */
+
+#ifdef HAVE_STRERROR
+ extern char *strerror OF((int));
+# define zstrerror(errnum) strerror(errnum)
+#else
+# define zstrerror(errnum) ""
+#endif
+
+#if defined(pyr)
+# define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+ * You may have to use the same strategy for Borland C (untested).
+ * The __SC__ check is for Symantec.
+ */
+# define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+# define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+# define zmemcpy _fmemcpy
+# define zmemcmp _fmemcmp
+# define zmemzero(dest, len) _fmemset(dest, 0, len)
+# else
+# define zmemcpy memcpy
+# define zmemcmp memcmp
+# define zmemzero(dest, len) memset(dest, 0, len)
+# endif
+#else
+ extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+ extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
+ extern void zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef DEBUG
+# include <stdio.h>
+ extern int z_verbose;
+ extern void z_error OF((char *m));
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) {if (z_verbose>=0) fprintf x ;}
+# define Tracev(x) {if (z_verbose>0) fprintf x ;}
+# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+
+typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf,
+ uInt len));
+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+void zcfree OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+#endif /* _Z_UTIL_H */
diff --git a/cfe/docs/cfe.pdf b/cfe/docs/cfe.pdf
new file mode 100755
index 0000000..ae668a1
--- /dev/null
+++ b/cfe/docs/cfe.pdf
Binary files differ